美文网首页
使用 GCD Global 创建大量线程需要注意的问题

使用 GCD Global 创建大量线程需要注意的问题

作者: iOS104 | 来源:发表于2017-06-14 23:02 被阅读32次

    在tableView列表中,当列表内 Cell 过多,每个cell里面有个网络图片,网络图片自己去GCD Global 创建子线程去下载,然后在主线程里面显示,在快速滑动的时候就会出现这个问题。,偶尔会遇到这种问题:

    image.png
    • 大量的任务提交到后台队列时,某些任务会因为某些原因被锁住导致线程休眠,或者被阻塞,concurrent queue 随后会创建新的线程来执行其他任务。

    • 当这种情况变多时,或者 App 中使用了大量 concurrent queue 来执行较多任务时,App 在同一时刻就会存在几十个线程同时运行、创建、销毁。

    • 再例如,下面会造成卡顿甚至界面冻屏

    - (void)dispatchTest {
        for (NSInteger i = 0; i< 10000 ; i++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                [self dispatchTask:i];
            });
        }
    }
    - (void)dispatchTask:(NSInteger)index {
            //模拟耗时操作,比如DB,网络,文件读写等等
            sleep(10);
            NSLog(@"----:%ld", index);
    }
    
    • CPU 是用时间片轮转来实现线程并发的,尽管 concurrent queue 能控制线程的优先级,但当大量线程同时创建运行销毁时,这些操作仍然会挤占掉主线程的 CPU 资源。

    • dispatch_async 函数分发到全局队列不一定会新建线程执行任务,全局队列底层有一个的线程池,如果线程池满了,那么后续的任务会被 block 住,等待前面的任务执行完成,才会继续执行。如果线程池中的线程长时间不结束,后续堆积的任务会越来越多,此时就会存在 APP crash的风险。

    • 全局队列的底层是一个线程池,向全局队列中提交的 block,都会被放到这个线程池中执行,如果线程池已满,后续再提交 block 就不会再重新创建线程。

    相关文章

      网友评论

          本文标题:使用 GCD Global 创建大量线程需要注意的问题

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