美文网首页
OC多线程

OC多线程

作者: 小明讲啥故事 | 来源:发表于2020-10-17 15:34 被阅读0次
    队列创建
    - (void)testData {
        //串行队列的创建方法
        dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
        //并发队列的创建方法
        dispatch_queue_t queue1 = dispatch_queue_create("net.bujige.testQueue2", DISPATCH_QUEUE_CONCURRENT);
    }
    
    - (void)testData2 {
        //获取主队列的方法
        dispatch_queue_t queue = dispatch_get_main_queue();
        //主队列其实并不特殊。
        //主队列的实质上就是一个普通的串行队列,只是因为默认情况下,当前代码是放在主队列中的,
        //然后主队列中的代码,有都会放到主线程中去执行,所以才造成了主队列特殊的现象
    }
    
    - (void)testData3 {
        //获取全局并发队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //第一个参数表示队列优先级,一般用 DISPATCH_QUEUE_PRIORITY_DEFAULT。第二个参数暂时没用,用 0 即可。
    }
    
    线程与队列
    /**
    * 同步执行 + 并发队列
    * 特点:在当前线程中执行任务,不会开启新线程,执行完一个任务,再执行下一个任务。
    */
    - (void)syncConcurrent {
        NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
        NSLog(@"syncConcurrent---begin");
        dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);
    
        dispatch_sync(queue, ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        dispatch_sync(queue, ^{
            // 追加任务 2
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        dispatch_sync(queue, ^{
            // 追加任务 3
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        NSLog(@"syncConcurrent---end");
    }
    
    
    /**
    * 异步执行 + 并发队列
    * 特点:可以开启多个线程,任务交替(同时)执行。
    */
    - (void)asyncConcurrent {
        NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
        NSLog(@"asyncConcurrent---begin");
    
        dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);
    
        dispatch_async(queue, ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        dispatch_async(queue, ^{
            // 追加任务 2
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        dispatch_async(queue, ^{
            // 追加任务 3
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        NSLog(@"asyncConcurrent---end");
    }
    
    /**
     * 同步执行 + 串行队列
     * 特点:不会开启新线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务。
     */
    - (void)syncSerial {
        NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
        NSLog(@"syncSerial---begin");
    
        dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
    
        dispatch_sync(queue, ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        });
        dispatch_sync(queue, ^{
            // 追加任务 2
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        });
        dispatch_sync(queue, ^{
            // 追加任务 3
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        NSLog(@"syncSerial---end");
    }
    /**
     * 异步执行 + 串行队列
     * 特点:会开启新线程,但是因为任务是串行的,执行完一个任务,再执行下一个任务。
     */
    - (void)asyncSerial {
        NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
        NSLog(@"asyncSerial---begin");
    
        dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
    
        dispatch_async(queue, ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        });
        dispatch_async(queue, ^{
            // 追加任务 2
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        });
        dispatch_async(queue, ^{
            // 追加任务 3
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
        });
       [NSThread sleepForTimeInterval:7];
        NSLog(@"asyncSerial---end");
    }
    
    队列线程间通信
    /**
     * 线程间通信
     */
    - (void)communication {
        // 获取全局并发队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        // 获取主队列
        dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
        dispatch_async(queue, ^{
            // 异步追加任务 1
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
    
            // 回到主线程
            dispatch_async(mainQueue, ^{
                // 追加在主线程中执行的任务
                [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
                NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
            });
        });
    }
    /**
     * 栅栏方法 dispatch_barrier_async
     */
    - (void)barrier {
        dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);
    
        dispatch_async(queue, ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        });
        dispatch_async(queue, ^{
            // 追加任务 2
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        dispatch_barrier_async(queue, ^{
            // 追加任务 barrier
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"barrier---%@",[NSThread currentThread]);// 打印当前线程
        });
    
        dispatch_async(queue, ^{
            // 追加任务 3
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
        });
        dispatch_async(queue, ^{
            // 追加任务 4
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"4---%@",[NSThread currentThread]);      // 打印当前线程
        });
    }
    
    /**
     * 延时执行方法 dispatch_after
     */
    - (void)after {
        NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
        NSLog(@"asyncMain---begin");
    
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            // 2.0 秒后异步追加任务代码到主队列,并开始执行
            NSLog(@"after---%@",[NSThread currentThread]);  // 打印当前线程
        });
        //需要注意的是:dispatch_after
        //方法并不是在指定时间之后才开始执行处理,而是在指定时间之后将任务追加到主队列中。
        //严格来说,这个时间并不是绝对准确的,但想要大致延迟执行任务,dispatch_after 方法是很有效的。
    }
    /**
     * 一次性代码(只执行一次)dispatch_once
     */
    - (void)once {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            // 只执行 1 次的代码(这里面默认是线程安全的)
        });
    }
    
    
    /**
     * 快速迭代方法 dispatch_apply
     */
    - (void)apply {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
        NSLog(@"apply---begin");
        dispatch_apply(6, queue, ^(size_t index) {
            NSLog(@"%zd---%@",index, [NSThread currentThread]);
        });
        NSLog(@"apply---end");
       // 如果是在串行队列中使用 dispatch_apply,那么就和 for 循环一样,按顺序同步执行。但是这样就体现不出快速迭代的意义了。
    
        //我们可以利用并发队列进行异步执行。比如说遍历 0~5 这 6 个数字,for 循环的做法是每次取出一个元素,逐个遍历。dispatch_apply 可以 在多个线程中同时(异步)遍历多个数字。
    
        //还有一点,无论是在串行队列,还是并发队列中,dispatch_apply 都会等待全部任务执行完毕,这点就像是同步操作,也像是队列组中的 dispatch_group_wait方法。
    }
    
    
    队列组
    /**
     * 队列组 dispatch_group_notify
     */
    - (void)groupNotify {
        NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
        NSLog(@"group---begin");
    
        dispatch_group_t group =  dispatch_group_create();
    
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 追加任务 2
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            // 等前面的异步任务 1、任务 2 都执行完毕后,回到主线程执行下边任务
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
    
            NSLog(@"group---end");
        });
    }
    
    /**
     * 队列组 dispatch_group_wait
     */
    - (void)groupWait {
        NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
        NSLog(@"group---begin");
    
        dispatch_group_t group =  dispatch_group_create();
    
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 追加任务 2
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
        });
    
        // 等待上面的任务全部完成后,会往下继续执行(会阻塞当前线程)
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    
        NSLog(@"group---end");
    
    }
    
    /**
     * 队列组 dispatch_group_enter、dispatch_group_leave
     */
    - (void)groupEnterAndLeave {
        NSLog(@"currentThread---%@",[NSThread currentThread]);  // 打印当前线程
        NSLog(@"group---begin");
    
        dispatch_group_t group = dispatch_group_create();
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_group_enter(group);
        dispatch_async(queue, ^{
            // 追加任务 1
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
    
            dispatch_group_leave(group);
        });
    
        dispatch_group_enter(group);
        dispatch_async(queue, ^{
            // 追加任务 2
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"2---%@",[NSThread currentThread]);      // 打印当前线程
    
            dispatch_group_leave(group);
        });
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            // 等前面的异步操作都执行完毕后,回到主线程.
            [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
            NSLog(@"3---%@",[NSThread currentThread]);      // 打印当前线程
    
            NSLog(@"group---end");
        });
        //从 dispatch_group_enter、dispatch_group_leave
        //相关代码运行结果中可以看出:当所有任务执行完成之后,才执行 dispatch_group_notify 中的任务。
        //这里的dispatch_group_enter、dispatch_group_leave 组合,其实等同于dispatch_group_async。
    }
    

    相关文章

      网友评论

          本文标题:OC多线程

          本文链接:https://www.haomeiwen.com/subject/wlxfmktx.html