zoukankan      html  css  js  c++  java
  • 多线程初认识

    一、多线程的基本概念

    二、NSThread

    资源竞争原理图

    多条线程同时访问同一个资源
        //4.做耗时操作时,多个线程访问同一个资源
        self.ticketCount = 100;
        self.threadA = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
        self.threadB = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
        self.threadC = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
        self.threadA.name = @"售票员A";
        self.threadB.name = @"售票员B";
        self.threadC.name = @"售票员C";
        //启动线程
        [self.threadA start];
        [self.threadB start];
        [self.threadC start];
    //执行方法
    - (void)saleTicket{
        //锁:必须是全局唯一性的
        //1.注意加锁的位置
        //2.注意加锁的条件,多线程共享同一块资源
        //3.注意加锁是需要付出代价的,需要耗费性能
        //4.加锁的条件:线程同步
        //如果不加锁的话就会出错
            while (1) {
                @synchronized (self) {
                NSInteger count = self.ticketCount;
                if (count > 0) {
                    //耗时操作
                    for (NSInteger i = 0; i< 100000; i++) {
                    }
                    self.ticketCount = count -1;
                    NSLog(@"%@卖出去了一张票,还剩下%zd张票",  [NSThread currentThread].name,self.ticketCount);
                }else{
                    NSLog(@"票卖完了");
                    break;
                }
            }
        }
    }
    

     三、GCD

    四、NSOperation

    五、代码实例

    1.NSOperation

    2.GCD

     //1.异步函数+串行队列,开一条线程,队列中的任务是串行执行的
    dispatch_queue_t queue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
        dispatch_async(queue, ^{
            NSLog(@"download1----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"download2---%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"download3---%@",[NSThread currentThread]);
        });
    //2.异步函数+并行队列,开多条线程,队列中的任务是并行执行的
    dispatch_queue_t queue = dispatch_queue_create("current", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            NSLog(@"download1----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"download2---%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"download3---%@",[NSThread currentThread]);
        });
    //3.异步函数+主队列,所有任务都会在主线程中完成,不会开线程
      dispatch_queue_t queue = dispatch_get_main_queue();
        dispatch_async(queue, ^{
            NSLog(@"download1----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"download2---%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"download3---%@",[NSThread currentThread]);
        });
    //4.同步函数+串行队列,不会开线程,任务是串行执行的
     dispatch_queue_t queue = dispatch_queue_create("seria", DISPATCH_QUEUE_SERIAL);
        dispatch_sync(queue, ^{
            NSLog(@"downloadload1----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"downloadload2----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"download3---%@",[NSThread currentThread]);
        });
    //5.同步函数+并行队列,不会开线程,任务是并行执行的
      dispatch_queue_t queue = dispatch_queue_create("seria",DISPATCH_QUEUE_CONCURRENT);
        dispatch_sync(queue, ^{
            NSLog(@"download01-------%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"download02-------%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"download03-------%@",[NSThread currentThread]);
        });
    //6.//同步函数+主队列= 死锁,如果该线程在子线程中执行,那么所有队列就会在主线程执行
        //同步函数,会崩掉
        //同步函数:立刻马上执行,如果我没有执行完毕,那么后面的也别想执行
        //异步函数:如果我没有执行完毕,那么后面的也可以执行
    dispatch_queue_t queue = dispatch_get_main_queue();
        dispatch_sync(queue, ^{
            NSLog(@"download01------%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"download02------%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"download03------%@",[NSThread currentThread]);
        });
    //7.多线程下载图片
    //1.创建子线程下载图片
        //DISPATCH_QUEUE_PRIORITY_DEFAULT 0
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            //图片地址
            NSURL *url = [NSURL URLWithString:@"http://a.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=da0ec79c738da9774e7a8e2f8561d42f/c83d70cf3bc79f3d6842e09fbaa1cd11738b29f9.jpg"];
            //转换成二进制数据
            NSData *data = [NSData dataWithContentsOfURL:url];
            //转换为图片
            UIImage *image = [UIImage imageWithData:data];
            dispatch_async(dispatch_get_main_queue(), ^{
                //更新图片
                self.headImageView.image = image;
            });
        });
    //8.延时加载
       //延时加载1
    //    [self performSelector:@selector(task) withObject:nil afterDelay:2];
        //延时加载2,用于定时器,repeats是否重复
        [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(task) userInfo:nil repeats:NO];
        //延时加载3,GCD
        dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{
            NSLog(@"GCD-----%@",[NSThread currentThread]);
        });
    //9.栅栏函数
    //栅栏函数不能使用全局并发队列
        //什么是dispatch_barrier_async函数
        //毫无疑问,dispatch_barrier_async函数的作用与barrier的意思相同,在进程管理中起到一个栅栏的作用,它等待所有位于barrier函数之前的操作执行完毕后执行,并且在barrier函数执行之后,barrier函数之后的操作才会得到执行,该函数需要同dispatch_queue_create函数生成的concurrent Dispatch Queue队列一起使用
        //dispatch_barrier_async函数的作用
        //如果是3条线程,并发执行的话,1条线程后面加栅栏函数,必须线程1执行完,才会执行线程2,3
        
        //1.实现高效率的数据库访问和文件访问
        //2.避免数据竞争
    //获得全局并发队列
    //    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
        dispatch_queue_t queue = dispatch_queue_create("barrier", DISPATCH_QUEUE_CONCURRENT);
        //异步函数
        dispatch_async(queue, ^{
            for (NSInteger i = 0; i < 100; i++) {
                  NSLog(@"download01--%zd------%@",i,[NSThread currentThread]);
            }
        });
        dispatch_async(queue, ^{
            for (NSInteger i = 0; i < 100; i++) {
                  NSLog(@"download02----%zd----%@",i,[NSThread currentThread]);
            }
        });
        //栅栏函数
        dispatch_barrier_async(queue, ^{
            NSLog(@"==========================");
        });
        dispatch_async(queue, ^{
            for (NSInteger i = 0; i < 100; i++) {
                NSLog(@"download03--%zd------%@",i,[NSThread currentThread]);
            }
        });
        dispatch_async(queue, ^{
            for (NSInteger i = 0; i < 100; i++) {
                NSLog(@"download04----%zd----%@",i,[NSThread currentThread]);
            }
        });
    //10.GCD的快速迭代
    //1.拿到文件的路径
        NSString *fromPath = @"/Users/xingzai/Desktop/Tools";
        //2.获取文件的路径
        NSString *toPath = @"/Users/xingzai/Desktop/Tool";
        //3.得到目录下所有文件
        NSArray *subPaths = [[NSFileManager defaultManager] subpathsAtPath:fromPath];
        //4.count
        NSInteger count = subPaths.count;
        //5.执行
        dispatch_apply(count, dispatch_get_global_queue(0, 0), ^(size_t index) {
           //拼接全路径,文件的路径
            NSString *fullPath = [fromPath stringByAppendingPathComponent:subPaths[index]];
            //拼接全路径,文件剪切到的路径
            NSString *toFullPath = [toPath stringByAppendingPathComponent:subPaths[index]];
            
            //参数一:文件的路径,参数二:文件剪切的位置
            [[NSFileManager defaultManager] moveItemAtPath:fullPath toPath:toFullPath error:nil];
        });
    //11.创建组队列
     //1.创建队列
        dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
        //2.创建队列祖
        dispatch_group_t group = dispatch_group_create();
        //3.异步函数
        /**1.封装对象
           2.把任务添加到队列中
           3.会监听执行情况,通知group
         */
        dispatch_group_async(group, queue, ^{
            NSLog(@"1-------%@",[NSThread currentThread]);
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"2-------%@",[NSThread currentThread]);
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"3------%@",[NSThread currentThread]);
        });
        //拦截通知,当队列组所有的任务都执行完以后需要执行下面的方法
        dispatch_group_notify(group, queue, ^{
            NSLog(@"线程全部执行完了");
        });
    //12.合成对象
    /**下载图片1,开子线程
           下载图片2,开子线程
           合成图片,并开子线程
         */
        //1.获取群组
        dispatch_group_t group = dispatch_group_create();
        //2.获取并发队列
        dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
        //3.下载图片,开启子线程
        dispatch_group_async(group, queue, ^{
            NSLog(@"打印当前线程------%@",[NSThread currentThread]);
            //3.1图片地址
            NSURL *url = [NSURL URLWithString:@"http://www.qbaobei.com/tuku/images/13.jpg"];
            //3.2下载二进制数据
            NSData *data = [NSData dataWithContentsOfURL:url];
            //3.3转换图片
            self.imageOne = [UIImage imageWithData:data];
        });
        //下载图片2
        dispatch_group_async(group, queue, ^{
            NSLog(@"-------%@",[NSThread currentThread]);
            //1.图片地址
            NSURL *url = [NSURL URLWithString:@"http://pic1a.nipic.com/2008-09-19/2008919134941443_2.jpg"];
            //2.下载二进制数据
            NSData *data = [NSData dataWithContentsOfURL:url];
            //3.转换图片
            self.imageTwo = [UIImage imageWithData:data];
        });
        //合成图片
        dispatch_group_notify(group, queue, ^{
            
            NSLog(@"-----------%@",[NSThread currentThread]);
            //1.创建图形上下文
            UIGraphicsBeginImageContext(CGSizeMake(320, 640));
            //2.画图形
            [self.imageOne drawInRect:CGRectMake(0, 0, 320, 320)];
            self.imageOne = nil;
            
            [self.imageTwo drawInRect:CGRectMake(0, 320, 320, 320)];
            self.imageTwo = nil;
            //3.根据上下文得到一张图片
            UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            //4.关闭上下文
            UIGraphicsEndImageContext();
            
            NSLog(@"%@",[NSThread currentThread]);
            dispatch_async(dispatch_get_main_queue(), ^{
                //更新UI
                self.headImageView.image = image;
            });
        });
        //由于dispatch_apply函数与dispatch_sync函数相同,会等待处理执行结束,因此推荐在dispatch_async函数中非同步地执行dispatch_apply函数
    
    将来的自己,会感谢现在不放弃的自己!
  • 相关阅读:
    ORACLE 按照指定顺序排序输出某些字段
    jsp 选择年份产生周下拉框
    jsp标签foreach
    润乾报表个人笔记
    eclipse加大服务器容器内存
    jsp input中使用fmt 格式化时间
    log4j简单使用java web项目--后台打印以及输出到文件
    log4j简单使用java项目--后台打印以及输出到文件
    声明:放弃博客园平台,近日将所有随笔转移到CSDN,并删除所有已公开的随笔。
    项目 Java 2 go的一些准备活动
  • 原文地址:https://www.cnblogs.com/TheYouth/p/6696729.html
Copyright © 2011-2022 走看看