iOS多线程归纳

pthread


NSThread


NSOperation


GCD

    一.并行队列

    1.向并行队列提交同步任务,(根据显示结果可知:所有任务全部在主线程执行,所有任务都是按顺序执行的)

//线程与线程之间的执行速度可能是不确定的
    //1. 创建一个并行队列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);

        //并行队列中提交多个异步任务,任务的顺序不能确定
        //同步提交任务任务的顺序可以确定
        dispatch_sync(concurrentQueue, ^{
            
            if ([NSThread isMainThread]) {
                NSLog(@"主线程");
            }else{
                NSLog(@"非主线程");
            }
            
            for (int i = 0; i < 100; i++) {
                NSLog(@"任务一:%d", i);
            }
        });
        NSLog(@"---1---");
        dispatch_sync(concurrentQueue, ^{
            if ([NSThread isMainThread]) {
                NSLog(@"主线程");
            }else{
                NSLog(@"非主线程");
            }

            for (int i = 0; i < 100; i++) {
                NSLog(@"任务二:%d", i);
            }
        });
        NSLog(@"---2---");
        dispatch_sync(concurrentQueue, ^{
            if ([NSThread isMainThread]) {
                NSLog(@"主线程");
            }else{
                NSLog(@"非主线程");
            }

            for (int i = 0; i < 100; i++) {
                NSLog(@"任务三:%d", i);
            }
        });
         NSLog(@"---3---");

    2.向并行队列提交异步任务(根据结果:所有任务都是在非主线程中执行的,而且任务执行的顺序是不确定的)

//并行队列中提交多个异步任务,任务的顺序不能确定
    dispatch_async(concurrentQueue, ^{
        
        if ([NSThread isMainThread]) {
            NSLog(@"主线程");
        }else{
            NSLog(@"非主线程");
        }
        
        for (int i = 0; i < 100; i++) {
            NSLog(@"任务一:%d", i);
        }
    });
    NSLog(@"---1---");
    dispatch_async(concurrentQueue, ^{
        if ([NSThread isMainThread]) {
            NSLog(@"主线程");
        }else{
            NSLog(@"非主线程");
        }
        
        for (int i = 0; i < 100; i++) {
            NSLog(@"任务二:%d", i);
        }
    });
    NSLog(@"---2---");
    dispatch_async(concurrentQueue, ^{
        if ([NSThread isMainThread]) {
            NSLog(@"主线程");
        }else{
            NSLog(@"非主线程");
        }
        
        for (int i = 0; i < 100; i++) {
            NSLog(@"任务三:%d", i);
        }
    });
    NSLog(@"---3---");

     

    二.串行队列

   1.向串行队列同步提交任务(从结果可知:所有任务都在主线程中执行,所有任务都是按顺序执行的)

//1. 创建串行队列,一个串行队列对应一个线程
    //1.1. 第一个参数是队列的名称
    //1.2. 第二个参数是队列的类型,NULL表示串行队列
    dispatch_queue_t serialQueue = dispatch_queue_create("com.serialQueue", DISPATCH_QUEUE_SERIAL);
    //2. 如果任务在不同的线程中执行,那么它们的执行顺序是不确定的
    dispatch_sync(serialQueue, ^{
        
        if ([NSThread isMainThread]) {
            NSLog(@"主线程");
        }else{
            NSLog(@"非主线程");
        }
        
        for (int i = 0; i < 100; i++) {
            NSLog(@"任务一:%d", i);
        }
    });
    
    NSLog(@"---1---");
    dispatch_sync(serialQueue, ^{
        
        if ([NSThread isMainThread]) {
            NSLog(@"主线程");
        }else{
            NSLog(@"非主线程");
        }
            for (int i = 0; i < 100; i++) {
                NSLog(@"任务二:%d", i);
            }
    });
        
        NSLog(@"---2---");
        dispatch_sync(serialQueue, ^{
            
            if ([NSThread isMainThread]) {
                NSLog(@"主线程");
            }else{
                NSLog(@"非主线程");
            }
                for (int i = 0; i < 100; i++) {
                    NSLog(@"任务三:%d", i);
                }
            });
            NSLog(@"---3---");

  2.向串行队列提交异步任务(从结果可知:所有的任务都是在非主线程中执行的,所有的任务都是按顺序执行的)

dispatch_async(serialQueue, ^{
        
        if ([NSThread isMainThread]) {
            NSLog(@"主线程");
        }else{
            NSLog(@"非主线程");
        }
        
        for (int i = 0; i < 100; i++) {
            NSLog(@"任务一:%d", i);
        }
    });
    
    NSLog(@"---1---");
    dispatch_async(serialQueue, ^{
        
        if ([NSThread isMainThread]) {
            NSLog(@"主线程");
        }else{
            NSLog(@"非主线程");
        }
        for (int i = 0; i < 100; i++) {
            NSLog(@"任务二:%d", i);
        }
    });
    NSLog(@"---2---");
    dispatch_async(serialQueue, ^{
        
        if ([NSThread isMainThread]) {
            NSLog(@"主线程");
        }else{
            NSLog(@"非主线程");
        }
        for (int i = 0; i < 100; i++) {
            NSLog(@"任务三:%d", i);
        }
    });
    NSLog(@"---3---");

结果对比:

  

iOS多线程归纳_第1张图片

iOS多线程归纳_第2张图片

iOS多线程归纳_第3张图片

iOS多线程归纳_第4张图片

    总结:

1.不管是串行队列还是并行队列,同步提交任务都是在主线程中执行的,异步提交任务都是在非主线程中执行的(这里相对于3.4来讲的)

2.并行队列的任务,如果不在同一线程,可以与主线程同时执行,主线程中的任务优先其他线程的任务执行,但不排除其他线程的任务和主线程的任务同时间进行

3.同步提交任务,任务所在的线程与提交任务所在的线程是一样的

4.异步提交任务,任务所在的线程与提交任务所在的线程是不一样的

5.同一线程,所有任务都是先进先出按顺序来的(串行同步,并行同步都在主线程)

6.串行异步,任务在同一个线程,任务所在的线程与提交任务所在的线程是不一样的(所以出现任务一和主线程的任务先执行,任务二和任务三后执行,因为任务一二三在同一个线程)

7.并行异步,任务在不同线程,任务所在的线程与提交任务所在的线程是不一样的(所以出现任务和主线程的任务都是同时执行)

所以根据上面的总结可以体会到,任务的执行顺序和会不会阻塞,我门只需要判断清楚任务所在的线程就可以了,不同线程可以同时执行,同一线程只能按顺序执行

最后只需记住多个任务同时执行用: 并行异步  两个任务同时执行用:串行异步  所有任务按先后顺序执行 :串行同步,并行同步  但是这里只是相对于一个线程编程的时候,比如主线程,如果在主线程里面创建一个其他的线程,然后同步提交任务,我们是不是也可以实现两个甚至是多个任务同时运行了,这个还有待验证


    三.界面假死与死锁

    概念这里参考 http://www.mamicode.com/info-detail-1010323.html 为了不麻烦就直接复制粘贴了

  首先明确一下“同步&异步”“串行&并发”这两组基本概念:

同步执行:比如这里的dispatch_sync,这个函数会把一个block加入到指定的队列中,而且会一直等到执行完blcok,这个函数才返回。因此在block执行完之前,调用dispatch_sync方法的线程是阻塞的。

与之对应的就有“异步执行”的概念:

异步执行:一般使用dispatch_async,这个函数也会把一个block加入到指定的队列中,但是和同步执行不同的是,这个函数把block加入队列后不等block的执行就立刻返回了。

接下来看一看另一组相对的概念:“串行&并发”

串行队列:比如这里的dispatch_get_main_queue。这个队列中所有任务,一定按照先来后到的顺序执行。不仅如此,还可以保 证在执行某个任务时,在它前面进入队列的所有任务肯定执行完了。对于每一个不同的串行队列,系统会为这个队列建立唯一的线程来执行代码。

与之相对的是并发队列:

并发队列:比如使用dispatch_get_global_queue。这个队列中的任务也是按照先来后到的顺序开始执行,注意是开始,但是它们的执行结束时间是不确定的,取决于每个任务的耗时。对于n个并发队列,GCD不会创建对应的n个线程而是进行适当的优化

    总结一下,到底什么是死锁。首先,虽然刚刚我们提到了队列和线程,以及它们之间的对应关系,但是死锁一定是针对线程 而言的,队列只是GCD给出的抽象数据结构。所谓的死锁,一定是发生在一个或多个线程之间的。那么死锁和线程阻塞的关系呢,可以这么理解,双向的阻塞导致 了死锁。因为阻塞是线程中经常发生的事情,最多就是主线程的阻塞影响了用户体验。而一旦出现了双向的阻塞,就导致了死锁。我们可以看到,主线程是串行的, 在执行某一个任务的时候线程被阻塞了,而这个任务(dispatch_sync)在执行时,又要求阻塞主线程,从而导致了互相的阻塞,也就是死锁

分析:如果阻塞时间过长久会形成“界面假死”,如果双向阻塞就会形成死锁,这两种情况的形成我们就不考虑异步提交了,因为异步提交是根本不会形成阻塞,所以我们只看同步提交的情况

  //1. 主队列里的任务一定在主线程上执行
    //2. 不应该在主线程中执行耗时的任务,否则会导致主线程阻塞,从而使界面“假死”
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t serialQueue = dispatch_queue_create("com.serialQueue", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    
    dispatch_sync(concurrentQueue, ^{
        
        if ([NSThread isMainThread]) {
            NSLog(@"主线程");
        }else{
            NSLog(@"非主线程");
        }

        //获取当前时间,秒钟
        CFAbsoluteTime begin = CFAbsoluteTimeGetCurrent();
        
        //整个管理文件或者文件夹
        [[NSFileManager defaultManager] copyItemAtPath:@"/Users/zhouzhi/百度云同步盘/电子专业书籍" toPath:@"/Users/zhouzhi/Desktop/电子书" error:nil];
        
        //获取结束时间点
        CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
        //打印消耗的时间
        NSLog(@"%.2f秒", end - begin);
    });
    NSLog(@"任务执行完成了");

 结果分析:

iOS多线程归纳_第5张图片


    除了同步提交任务到mainQueue会形成死锁,其他都是界面假死

   看到这个结果,到这里我已经云里雾里了,为什么mainQueue会形成死锁,其他的没有形成死锁,我提交任务在主线程进行,然后任务的执行也是在主线程执行,为什么没形成死锁而是阻塞

还有上面的“串行同步”,“并行同步”提交任务和任务运行也都是在主线程中进行的,为什么还可以按顺序执行,求解答,我到底错在了哪里,难道我这整个想法都是错的?





你可能感兴趣的:(iOS多线程归纳)