GCD随笔

*串行与并行

串行队列与并发队列都是基于队列,所以遵循先进先出的原则。串行执行时,各个任务按顺序执行,完成一个后才能进行下一个;并发执行各个任务也是按顺序开始执行,但是无需等待前一个完成才能执行。

单个线程的并行队列采用并发方式,而多核CPU可同时开启多线程并行执行任务。

*同步和异步

同步不能开启新的线程,异步可以开启新的线程;所以并发队列的并发功能只有在异步下才有效。

同步:在发出一个功能调用时,在没有得到返回结果前,程序不会往下执行。

异步:在发出一个功能调用后即刻返回,程序继续往下执行。

*GCD的使用

一,创建队列

可以使用dispatch_queue_create来创建队列,需要传两个参数;第一个参数表示队列唯一标识,一般采用如应用程序ID一样的逆序全称域名来标识,第二个参数用来识别是串行队列还是并发以列,DISPATCH_QUEUE_SERIAL表示串行以列,DISPATCH_QUEUE_CONCURRENT 表示并发队列。 

eg:

dispatch_queue_t queue1 = dispatch_queue_create("com.test.mySerialQueue",DISPATCH_QUEUE_SERIAL)

dispatch_queue_t queue2 = dispatch_queue_create("com.test.myConncurrentQueue",DISPATCH_QUEUE_CONCURRENT)

GCD提供两种默认的队列:

1,特殊的串行队列:主列队,放在主队列中的任务都会放到主线程中去执行,队列获取方式:

dispatch_queue_t  mainQueue = dispatch_get_main_queue()

2,全局并发队列:需要传递两个参数,第一个表示优先级,一般用DISPATCH_QUEUE_PRIORITY_DEFAULT,第二个暂时没用,传0即可。

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)

二,任务执行方法

1,同步执行任务

dispatch_sync(queue, ^{

//执行任务

});

2,异步执行任务

dispatch_async(queue,^{

//do something

});

同步/异步+并发/串行队列执行情况:

方式 并发队列 串行队列 主队列
同步执行 没有开启新线程 执行任务时没有开启新线程

*主线程调用:会出线死锁

*其它线程调用不会开新线程,串行执行

异步执行 有开启新线程,并发执行任务有开启新线程 主线程串行执行任务

三,栅栏操作

 在我们需要异步执行两组操作,并且当前一组操作需要等待之前操作执行完后才开始,这就需要一个栅栏操作。

dispatch_barrier_ async异步栅栏、dispatch_barrier_ sync同步栅栏

*在执行栅栏之前的异步操作完成之后,才开始执行栅栏函数,最后再执行栅栏函数后的异步任务。

*多个栅栏函数串行执行

*在使用栅栏函数时,使用自定义并发队列才有意义。如果用的是串行队列或者系统提供的全局并发队列,这个栅栏函数的作用等同于一个同步函数的作用。

四,延迟执行方法:dispatch_after

eg:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)2.0*NSEC_PER_SEC),dispatch_get_main_queue(),^{

});

*dispatch_after并不是在指定时间后开始执行处理,而是在指定时间之后将任务追加到某个队列中,所以时间只是个大概

五,GCD单例执行:dispatch_once

六,快速迭代方法:dispatch_apply当传入并发队列时会利用多核开启多线程执行以提高效率,会等待全部任务执行完毕再执行下步操作

 dispatch_queue_t cQ = dispatch_queue_create("myCq", DISPATCH_QUEUE_CONCURRENT);

 dispatch_apply(6, cQ, ^(size_t iteration) {

  });

七,GCD队列组:dispatch_group

1,调用队列组的dispatch_group_async(先把任务放入队列中,再将队列放入组中)

2,或使用dispatch_group_enter、dispatch_group_leave来实现跟dispatch_group_async相同的效果

3,调用dispatch_group_notify回到指定的队列中执行指定的任务,或是使用dispatch_group_wait回到当前线程中继续向下执行操作

4,dispatch_group_notify和dispatch_group_wait的区别在于前者不会阻塞当前线程,而后者会阻塞线程直到指定的时间前group中的任务完成才进行后继操作

eg1:

  dispatch_queue_t cQ = dispatch_queue_create("myCq", DISPATCH_QUEUE_SERIAL);

  dispatch_group_t cG = dispatch_group_create();

    dispatch_group_async(cG, cQ, ^{

   //something

    });

    dispatch_group_async(cG, cQ, ^{ 

 //something

    });

//    dispatch_group_notify(cG, dispatch_get_main_queue(), ^{

//      something

//    });

    dispatch_group_wait(cG, DISPATCH_TIME_FOREVER);

eg2:

 dispatch_queue_t cQ = dispatch_queue_create("myCq", DISPATCH_QUEUE_CONCURRENT);

 dispatch_group_t cG = dispatch_group_create();

 dispatch_group_enter(cG);

 dispatch_async(cQ,^{

        dispatch_group_leave(cG);

});

dispatch_group_enter(cG);

dispatch_async(cQ,^{

        dispatch_group_leave(cG);

});

//    dispatch_group_notify(cG, dispatch_get_main_queue(), ^{ 

//    });

dispatch_group_wait(cG, DISPATCH_TIME_FOREVER);

八,GCD信号量,可用于保证线程安全,为线程加锁或保持线程同步

信号量是一个整型值,在创建的时候会有一个初始值。当执行dispatch_semaphore_signal发送信号的时候信号量会加1,dispatch_semaphore_wait在信号量小于或等于0的时候会一直等待,直到超时,并且会阻塞该线程,当信号量大于0时会继续执行并对信号量执行减1操作。

Dispatch Semaphore提供了三个函数。

dispatch_semaphore_create: 创建一个Semaphore并初始化信号的总量
dispatch_semaphore_signal: 发送一个信号, 让信号总量加1
dispatch_semaphore_wait: 可以使总信号量减1,当信号总量为0时就会一直等待(阻塞所在线程),否则就可以正常执行。 

 

posted @   Major1698  阅读(21)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示