• iOS多线程拾贝------操作巨人编程


    iOS多线程拾贝------操作巨人编程

    多线程

    基本

    • 实现方案:pthread - NSThread - GCD - NSOperation

      • Pthread

        • 多平台,可移植
        • c语言,要程序员管理生命周期
        • 创建
        //这里已经开启了多线程,直接在这里调用子线程想要调用的代码
        void * run(void *pramga) {
        NSLog(@"-------");
        return NULL;
        }
        
        - (IBAction)btnClick:(id)sender {
        pthread_t pthread;
        pthread_create(&pthread, NULL, run, NULL);
        }
      • NSThread

        • 面向对象,简单实用
        • 创建
        //隐式创建并启动线程
        [NSThread detachNewThreadSelector:@selector(threadRun:) toTarget:self withObject:@"etund"];
        或者
        //创建线程并且启动线程
        [self performSelectorInBackground:@selector(threadRun:) withObject:@"etund"];
        或者
        //上述两个优点是可以快速的创建并启动线程,方便快捷,但是不能对线程进行多余属性的设置,而下面一种方法就可以对线程实例属性的设置,但是要记得要手动开启线程。
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadRun:) object:@"etund"];
        [thread start];

    GCD

    • 听说全称是叫“牛逼的中枢调度器”,但是我还是喜欢叫大中央调度
    • 纯C语言,有很多强大的函数
    • 优势:(纯属板书)
      • GCD是苹果公司为多核的并行运算提出的解决方案
      • GCD会自动利用更多的CPU内核(比如双核、四核)
      • GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
      • 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
    • 核心:清楚什么是任务,队列
      • 串行与并行不能决定是否要开启新县城
      • 并行表明具有创建新线程的能力,但不一定创建新线程
    • 常用GCD内容

      • 串行同步(并行同步/全局队列同步),由于串行同步,并行同步,以及全局队列同步都是不创建线程按顺序执行,所以归为一类来讲。(不开任何子线程,在主线程中执行)

        //串行
        dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_SERIAL);
        //并行
        //dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_CONCURRENT);
        dispatch_sync(queue, ^{
        
          NSLog(@"%@---1",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
          NSLog(@"%@----2",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
          NSLog(@"%@----3",[NSThread currentThread]);
        });
        运行结果
        2015-07-08 19:09:39.611 Pthread-多平台[63090:302902] <NSThread: 0x7fc79142c1d0>{number = 1, name = main}---1
        2015-07-08 19:09:39.612 Pthread-多平台[63090:302902] <NSThread: 0x7fc79142c1d0>{number = 1, name = main}----2
        2015-07-08 19:09:39.612 Pthread-多平台[63090:302902] <NSThread: 0x7fc79142c1d0>{number = 1, name = main}----3
      • 串行异步 (开启一个子线程,在子线程中执行)

        dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_SERIAL);
        dispatch_async(queue, ^{
          NSLog(@"%@---1",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
          NSLog(@"%@---2",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
          NSLog(@"%@---3",[NSThread currentThread]);
        });
        
        /*运行结果
        2015-07-08 19:25:37.811 Pthread-多平台[68041:316565] <NSThread: 0x7fb35850fe30>{number = 3, name = (null)}---1
        2015-07-08 19:25:37.811 Pthread-多平台[68041:316565] <NSThread: 0x7fb35850fe30>{number = 3, name = (null)}---2
        2015-07-08 19:25:37.811 Pthread-多平台[68041:316565] <NSThread: 0x7fb35850fe30>{number = 3, name = (null)}---3
        */
      • 并行异步(全局队列异步)虽然线程的执行顺序不一样,但是任务从队列里面拿出来放进线程的顺序是按照先进先出的这是根本,基础。(有几个任务,开启几个子线程,在各自的子线程中执行)

        dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
          NSLog(@"%@---1",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
          NSLog(@"%@---2",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
          NSLog(@"%@---3",[NSThread currentThread]);
        });
        //   虽然线程的执行顺序不一样,但是任务从队列里面拿出来放进线程的顺序是按照先进先出
        /*
        *2015-07-08 19:27:46.060 Pthread-多平台[68694:318231] <NSThread: 0x7f9a89c126b0>{number = 4, name = (null)}---2
        2015-07-08 19:27:46.060 Pthread-多平台[68694:318230] <NSThread: 0x7f9a8c211400>{number = 5, name = (null)}---3
        2015-07-08 19:27:46.060 Pthread-多平台[68694:318171] <NSThread: 0x7f9a89f9efe0>{number = 3, name = (null)}---1
        */
      • 主队列异步,不开任何子线程,在主线程中运行,也对应了那句话,异步队列只是具有开启子线程的能力,但是不一定开子线程。

        //    主队列异步(不开线程)
        dispatch_async(dispatch_get_main_queue(), ^{
          NSLog(@"%@---1",[NSThread currentThread]);
        });
        dispatch_async(dispatch_get_main_queue(), ^{
          NSLog(@"%@---2",[NSThread currentThread]);
        });
        dispatch_async(dispatch_get_main_queue(), ^{
          NSLog(@"%@---3",[NSThread currentThread]); ;
        });
        /*
        2015-07-08 19:34:25.440 Pthread-多平台[70710:322816] <NSThread: 0x7fe0d1418200>{number = 1, name = main}---1
        2015-07-08 19:34:25.440 Pthread-多平台[70710:322816] <NSThread: 0x7fe0d1418200>{number = 1, name = main}---2
        2015-07-08 19:34:25.440 Pthread-多平台[70710:322816] <NSThread: 0x7fe0d1418200>{number = 1, name = main}---3
        */
      • 主队列同步

        - (void)gcdTest_2_4{
          NSLog(@"=-=-=-");
          //    主队列同步(阻塞)
          dispatch_sync(dispatch_get_main_queue(), ^{
              NSLog(@"%@---1",[NSThread currentThread]);
          });
          dispatch_sync(dispatch_get_main_queue(), ^{
              NSLog(@"%@---2",[NSThread currentThread]);
          });
          dispatch_sync(dispatch_get_main_queue(), ^{
              NSLog(@"%@---3",[NSThread currentThread]);
          });
          NSLog(@"=-=-=-");
        }

        ------------至此,基本GCD队列已经被差不多就这样了,下面来一下有趣的用法

      • GCD队列组,有这么一个需求,你的一个步骤要在其他步骤完成之后才能完成,也就是后续步骤要依赖于前期步骤,这是GCD队列组以及Barrier队列(栅栏队列)不失为一个好办法,
    //GCD队列组方式
            //    (线程组)(线程通讯)
    //    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_group_t group = dispatch_group_create();
        //    加载图片1
        dispatch_group_async(group, queue, ^{
            NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/d788d43f8794a4c2e882eb8b0df41bd5ac6e39e8.jpg"];
            NSData *data = [NSData dataWithContentsOfURL:url];
            self.image1 = [UIImage imageWithData:data];
        });
        //    加载图片2
        dispatch_group_async(group, queue, ^{
            NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/image/pic/item/ac6eddc451da81cbd668501c5666d01608243151.jpg"];
            NSData *data = [NSData dataWithContentsOfURL:url];
            self.image2 = [UIImage imageWithData:data];
        });
    
        //    合并
        dispatch_group_notify(group, queue, ^{
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);
            [self.image1 drawAsPatternInRect:CGRectMake(0, 0, 50, 100)];
            [self.image2 drawAsPatternInRect:CGRectMake(50, 0, 50, 100)];
            UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            //GCD线程之间的通信
            dispatch_async(dispatch_get_main_queue(), ^{
                self.myView.image = image;
            });
            });
    
    //栅栏dispatch_barrier方式
            dispatch_queue_t queue = dispatch_queue_create("etund", DISPATCH_QUEUE_CONCURRENT);//创建多个线程
        dispatch_async(queue, ^{
            NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/d788d43f8794a4c2e882eb8b0df41bd5ac6e39e8.jpg"];
            NSData *data = [NSData dataWithContentsOfURL:url];
            self.image1 = [UIImage imageWithData:data];
        });
        dispatch_async(queue, ^{
            NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/image/pic/item/ac6eddc451da81cbd668501c5666d01608243151.jpg"];
            NSData *data = [NSData dataWithContentsOfURL:url];
            self.image2 = [UIImage imageWithData:data];
        });
    
        dispatch_barrier_async(queue, ^{
    
        });
    
        dispatch_async(queue, ^{
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), NO, 0);
            [self.image1 drawAsPatternInRect:CGRectMake(0, 0, 50, 100)];
            [self.image2 drawAsPatternInRect:CGRectMake(50, 0, 50, 100)];
            UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            dispatch_async(dispatch_get_main_queue(), ^{
                self.myView.image = image;
            });
        });
    • 延迟加载

      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        // 2秒后异步执行这里的代码...
      });
    • 快速迭代,当我们不需要注重迭代的顺序,只需要快速获得子元素的时候,GCD的快速迭代为你提供了途径

        //    (快速迭代)
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_apply(self.view.subviews.count, queue, ^(size_t index) {
            id obj = self.view.subviews[index];
            NSLog(@"---%zu---%@",index,obj);
        });
        /*
        2015-07-08 22:26:39.851 Pthread-多平台[972:17366] ---0---<_UILayoutGuide: 0x7fd86b644e00; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x7fd86b643ab0>>
        2015-07-08 22:26:39.851 Pthread-多平台[972:17444] ---2---<UIImageView: 0x7fd86b645ba0; frame = (100 100; 100 100); clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x7fd86b643290>>
        2015-07-08 22:26:39.851 Pthread-多平台[972:17435] ---1---<_UILayoutGuide: 0x7fd86b6457b0; frame = (0 568; 0 0); hidden = YES; layer = <CALayer: 0x7fd86b644040>>
         */
    • once一次性代码(单例模式设计),有时候我们需要用到单例模式做一些操作例如:传值时,就会用到单例设计模式,设计单例模式的方法很多,其中最重要的是要做到线程安全,而GCD就提供了这么一个结构体来保证在创建单例过程中的线程安全
    ETPerson.h
    + (instancetype)sharePerson;
    ETPerson.m
    @implementation ETPerson
    static ETPerson *_person;
    
    + (instancetype)sharePerson{
        static dispatch_once_t onceDispatch;
        dispatch_once(&onceDispatch, ^{
            _person = [[ETPerson alloc] init];
        });
        return _person;
    }
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone{
        static dispatch_once_t onceDispatch;
        dispatch_once(&onceDispatch, ^{
            _person = [super allocWithZone:zone];
        });
        return _person;
    }
    
    - (id)copyWithZone:(NSZone *)zone{
        return _person;
    }
    @end
    调用
    //    onece(单例)
        NSLog(@"%@----%@------%@-------%@------%@-----%@",[[ETPerson alloc] init],[[ETPerson alloc] init],[ETPerson copy],[ETPerson copy],[ETPerson sharePerson],[ETPerson sharePerson]);
        /*运行结果
         2015-07-08 23:26:57.292 Pthread-多平台[1350:37528] <ETPerson: 0x7fc4bb4041c0>----<ETPerson: 0x7fc4bb4041c0>------ETPerson-------ETPerson------<ETPerson: 0x7fc4bb4041c0>-----<ETPerson: 0x7fc4bb4041c0>
         */
    -----------------------------------------分割线-----------07-09更----------------------------------- 

    NSOperation

    • NSOperation是对GCD的封装,既然封装了,那么就没有GCD那么好玩,但是同时也更加便捷的实现以下常用的功能。
    • 创建:NSOperation是一个抽象类,不能实例化,但可以通过他的子类来使用,子类分别是NSBlockOperation和NSInvocationOperation,创建方式如下。

      //NSBlockOperation
        NSBlockOperation *opeaBlock = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"----1---%@-",[NSThread currentThread]) ;
        }];
        [opeaBlock start];
        或者
      //    NSInvocationOperation
        NSInvocationOperation *invoOpera = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:@"etund"];
        [invoOpera start];
        /*运行结果
         2015-07-09 14:00:18.610 Pthread-多平台[91622:193993] ----1---<NSThread: 0x7fc26ae193c0>{number = 1, name = main}---- etund
         */
    • 此外,还可以通过自定义类继承NSOperation来使用NSOperation,注意在继承NSOperation的实现中把你想要执行的代码块放进- (void)main;里面就行。

    ETOperation.m
    - (void)main{
        NSLog(@"-----1-%@",[NSThread currentThread]);
    }
    //调用
    //      自定义NSOperation
        ETOpearation *operation = [[ETOpearation alloc] init];
        [operation start];
        /*运行结果
         2015-07-09 14:00:18.610 Pthread-多平台[91622:193993] ----1---<NSThread: 0x7fc26ae193c0>{number = 1, name = main}---- etund
         */
    • 以上线程都没有开启子线程,我们可以用NSOperationQueue与NSOperation结合使用来实现多线程操作,具体做法是把NSOperation实例加到NSOperationQueue队列中,当我们把实例加入队列中的时候,就不用主动调用start方法来开启线程了,线程会自动开启。
        //    NSOperationQueue
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    //    自定义NSOperation实例
        ETOpearation *operation =  [[ETOpearation alloc] init];
        NSBlockOperation *opeaBlock = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"----1---%@-",[NSThread currentThread]) ;
        }];
        NSInvocationOperation *invoOpera = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run:) object:@"etund"];
        [queue addOperation:opeaBlock];
        [queue addOperation:invoOpera];
        [queue addOperation:operation];
        /*运行结果
         2015-07-09 14:24:26.191 Pthread-多平台[98921:212686] -----1-<NSThread: 0x7ff1eab20440>{number = 5, name = (null)}
         2015-07-09 14:24:26.191 Pthread-多平台[98921:212687] ----1---<NSThread: 0x7ff1eab20190>{number = 4, name = (null)}-
         2015-07-09 14:24:26.191 Pthread-多平台[98921:212689] ----1---<NSThread: 0x7ff1eaa37910>{number = 3, name = (null)}---- etund
         */

    --------注意看上面运行结果,已经创建了多个线程了,至此我们成功的利用NSOperationQueue以及NSOperation实现多线程操作。

    • 我们也可以直接在队列里面添加线程代码块,就可以省去新建NSOperation实例
    //    NSOperationQueue
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [queue addOperationWithBlock:^{
            NSLog(@"=======1==%@",[NSThread currentThread]);
        }];
        [queue addOperationWithBlock:^{
            NSLog(@"=======2==%@",[NSThread currentThread]);
        }];
        [queue addOperationWithBlock:^{
            NSLog(@"=======3==%@",[NSThread currentThread]);
        }];
        [queue addOperationWithBlock:^{
            NSLog(@"=======4==%@",[NSThread currentThread]);
        }];
        [queue addOperationWithBlock:^{
            NSLog(@"=======5==%@",[NSThread currentThread]);
        }];
        /*运行结果
         2015-07-09 14:20:30.289 Pthread-多平台[97728:209415] =======3==<NSThread: 0x7ffdf2b90220>{number = 7, name = (null)}
         2015-07-09 14:20:30.289 Pthread-多平台[97728:209432] =======1==<NSThread: 0x7ffdf2b8fdc0>{number = 4, name = (null)}
         2015-07-09 14:20:30.289 Pthread-多平台[97728:209416] =======5==<NSThread: 0x7ffdf0e015a0>{number = 5, name = (null)}
         2015-07-09 14:20:30.289 Pthread-多平台[97728:209414] =======2==<NSThread: 0x7ffdf0c313e0>{number = 3, name = (null)}
         2015-07-09 14:20:30.289 Pthread-多平台[97728:209417] =======4==<NSThread: 0x7ffdf0c314c0>{number = 6, name = (null)}
         */
    • 注意:我们可以通过maxConcurrentOperationCount来设置改队列可以开启的最大线程数,最小是1,当设置为0的时候,不执行队列中的任务,当为1的时候为GCD中的串行同步(并行同步,主队列异步,全局队列同步)一样效果。

    -------------至此NSOperation的基本用法差不多涉及了,下面在来看看NSOperation封装带来的好处

    • 队列挂起,suspended这个属性可以控制当前线程队列的暂停和开启,在这里,已经默认你是对iOS多线程的任务有一定了解的,suspended为NO时,回执行完当前的NSOperation实例的任务,后面的任务不会在执行知道你开启

    • 队列挂起或开启如下。

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    //    NSOperationQueue
    //    挂起
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        self.queue = queue;
    
        [queue addOperationWithBlock:^{
            for (int i = 0; i < 5000; i ++) {
                NSLog(@"0--%d-----%@---",i,[NSThread currentThread]);
            }
        }];
    
        [queue addOperationWithBlock:^{
            for (int i = 0; i < 5000; i ++) {
                NSLog(@"1--%d-----%@---",i,[NSThread currentThread]);
            }
        }];
        [queue addOperationWithBlock:^{
            for (int i = 0; i < 5000; i ++) {
                NSLog(@"2--%d-----%@---",i,[NSThread currentThread]);
            }
        }];
    
     //当执行一个任务的时候收到suspended为NO,就会执行完当前循环,停在当前任务。
    
    }
    //完成一个点击事件就会改变suspended的状态
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
        self.queue.suspended = !self.queue.isSuspended;
    }
    • 队列取消,把当前队列后面的NSOperation实例全部清除掉,相对于挂起,取消是不可逆的。
      • 所以在系统自定义的NSOperation实例中,取消跟挂起取YES结果一样
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [queue addOperationWithBlock:^{
            for (int i = 0 ; i < 5000;i++){
                NSLog(@"----1---%@---%d-",[NSThread currentThread],i);
            }
        }];
    
        [queue addOperationWithBlock:^{
            for (int i = 0 ; i < 5000;i++){
                NSLog(@"----2---%@--%d--",[NSThread currentThread],i);
            }
        }];
    
        [queue addOperationWithBlock:^{
            for (int i = 0 ; i < 5000;i++){
                NSLog(@"----3---%@--%d--",[NSThread currentThread],i);
            }
        }];
    
        self.queue = queue;
    }
    
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
        [self.queue cancelAllOperations];
    }
    - 在自定义的NSOperation类中,当然可以把他看做一个普通的NSOperation实例对象,但是系统给NSOperation提供一个cancel属性,所以他的可控粒度更小,控制起来比较个性,要做到这一点,要在我们自定义类里面重写的main方法里面做功夫
    ETOperation.m
    //这样就可以做到在任务里想停就马上停。
    for (int i = 0; i < 5000; i++) {
            if (self.isCancelled) return;
            NSLog(@"%d---1-------%@",i,[NSThread currentThread]);
        }
    调用
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [queue addOperation:[[ETOpearation alloc] init]];
        self.queue = queue;
    }
    
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
        [self.queue cancelAllOperations];
    }
    • 操作依赖,NSOperation的作用在一定程度上类似于GCD的栅栏队列(Barrier)和队列组,也就是后续步骤要在前面步骤的基础上才能执行。
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        __block int i;
        __block int j;
        NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
            i = 10;
            j = 10;
        }];
    
        NSBlockOperation *blockOperation_0 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"%d",j+i);
        }];
    
        [blockOperation_0 addDependency:blockOperation];
        [queue addOperation:blockOperation];
        [queue addOperation:blockOperation_0];
    
    }
    • 上述代码没有什么实际意义,拿上面的一个需求吧,例如,下载图片,合成图片。
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        __block UIImage * image1;
        __block UIImage * image2;
        NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
            image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/d788d43f8794a4c2e882eb8b0df41bd5ac6e39e8.jpg"]]];
            image2 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://h.hiphotos.baidu.com/image/pic/item/ac6eddc451da81cbd668501c5666d01608243151.jpg"]]];
        }];
    
        NSBlockOperation *blockOperation_0 = [NSBlockOperation blockOperationWithBlock:^{
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), NO, 0);
            [image1 drawAsPatternInRect:CGRectMake(0, 0, 100, 200)];
            [image2 drawAsPatternInRect:CGRectMake(100, 0, 100, 200)];
            UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                self.myView.image = image;
            }];
        }];
    
        [blockOperation_0 addDependency:blockOperation];
        [queue addOperation:blockOperation];
        [queue addOperation:blockOperation_0];
    • 操作监听,在NSOperation属性中,有一个属性@property (copy) void (^completionBlock)(void)可以在某个操作执行完成时,在执行一段代码,有很多需求也用到这个属性,例如图片的下载,如上,可以试着把上面的那段代码改写,这里就随便写一段简单的代码来展示操作监听的强大。
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        __block int i;
        __block int j;
        NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
            i = 10;
            j = 10;
        }];
    
        blockOperation.completionBlock = ^{
            NSLog(@"%d",j+i);
        };
        [queue addOperation:blockOperation];
    }

     

    线程通信

    • 线程之间的通信,线程的通信,在一个进程中,线程往往不是鼓励存在的,多个线程之间需要经常进行通信
    • 线程间通信的体现
      • 在一个线程传递数据给另外一个线程
      • 在一个线程中执行完成任务后,转到另一个线程继续执行任务
    • NSThread的线程通信

      //这个方法是指在当前线程运行完后调到主线程里面运行
        - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
      //这个方法是指在当前线程运行完后调用另外一个线程里面运行
        - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait
    • GCD的线程通信,GCD的线程通信十分简单,只是在代码块里面调用代码块,直接上代码吧。
    从子线程回到主线程
    dispatch_async(
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 执行耗时的异步操作...
          dispatch_async(dispatch_get_main_queue(), ^{
            // 回到主线程,执行UI刷新操作
            });
    });
    至此,iOS里面简单的多线程GCD以及NSThread以及PThread部分就入门了,明天更新NSOPeration。
    -----------------------------------------分割线-----------07-09更-----------------------------------
    • NSOperation的线程通信
    
    
    //回到主线程
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
    
            }];
    
    //去子线程
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [queue addOperationWithBlock:^{
    
        }];
     
  • 相关阅读:
    Java
    oracle与mysql(2)
    oracle与mysql
    junit中的assert方法总结
    java Future用法和意义一句话击破
    Java序列化中的SerialVersionUid
    Nginx了解
    现如今的CDN网站加速技术,细说CDN
    slf4j日志的使用
    IDEA 快捷键整理
  • 原文地址:https://www.cnblogs.com/superYou/p/4631761.html
Copyright © 2020-2023  润新知