糖果派对官方网站_可以赌钱的糖果游戏_手机版
GCD的应用技艺

GCD的应用技艺

作者:网络编程    来源:未知    发布时间:2020-04-19 10:00    浏览量:

bb电子糖果派对 1

通过本小说你会到:

GCD的应用技艺。文中较详细介绍GCD队列,各类GCD使用格局,实比怎样运用Dispatch Source监听系统底层对象,剖判差异锁的性能相比较,实例GCD死锁情况。文中的德姆o在那 对着文章试着来调demo体会更加深哦,细细嚼消食好:卡塔尔

那七个词都以描摹当实施任务时是否供给考虑任何任务。串行:任务只好七个接着二个地试行现身:同时内,多少个任务能够是还要施行的

  • 多线程编程个中的基本概念
  • 如何堤防GCD八线程的读写难点

GCD归属系统级的线程处理,在Dispatch queue中实施要求进行的职分品质极其的高。GCD那块已经开源,地址 queue,用来确认保障先进来的职务先拿走实践。

那三个词是用来描写,被调用的函数在怎么样时候将调控权再次来到给调用者。同步:被调用的函数只会在施行完才将调整权给回调用者。异步:被调用的函数会立时将调控权再次来到给调用者,不管函数是不是实施完。因而异步函数不会拥塞当前经过。

GCD是Grand Central Dispatch的简单的称呼。为何采用GCD?

  • 和operation queue相同都以基于队列的面世编制程序API,他们通过集中管理我们协同使用的线程池。
  • 当着的5个分歧队列:运转在主线程中的main queue,3个不等优先级的后台队列(High Priority Queue,Default Priority Queue,Low Priority Queue),以致叁个预先级更低的后台队列Background Priority Queue
  • 可创建自定义队列:串行或并列队列。自定义日常坐落于Default Priority Queue和Main Queue里。
  • 操作是在十六线程上依旧单线程首若是看队列的档期的顺序和实市场价格势,并行队列异步实施技术在二十四线程,并行队列同步执行就只会在主线程实行了

能被三个线程同时实行的财富,且不会现出能源竞争、死锁、顺序错乱、优先级翻转等难题

使用GCD具备以下好处:

不能被现身实行的代码,不能被五个线程同期奉行,举个例子因为修改分享的财富还是变量,只要运维就能够立马崩溃大概是失误

  • GCD能修正app的响应手艺,通过将有个别相比耗时的天职运转在后台(background卡塔尔
  • GCD提供一个相比便于选择的面世模型。幸免有个别并发引起的Bug
  • 系统规范三个种类

bb电子糖果派对 2

为了越来越好地利用GCD,供给驾驭以下的关于线程和产出的概念。

如图,有一个变量存款和储蓄着17,然后线程A读取变量获得17,线程B也读取了这些变量。七个线程都进展了加1运算得,并写入18都变量。进而产生了崩溃。那正是race condition,四十多线程使用分享财富,而从不管教其余线程是一度终止使用分享财富

串行 vs 并发(Concurrent)

那三个词都以形容当施行职责时是还是不是供给思虑其他职分。

串行:任务只可以三个任何时候三个地施行现身:相同的时候内,七个任务能够是同时实践的

//全局队列,一个并行的队列dispatch_get_global_queue//主队列,主线程中的唯一队列,一个串行队列dispatch_get_main_queue

bb电子糖果派对 3

任务

能够总结地以为任务就是闭包。实际上,也得以通过函数指针来使用GCD,但大许多情状下会比较麻烦。

闭包正是一段能够被存放并传值的可调用代码块。

  • 自定义队列

如图,使用锁对线程正在接收的分享财富进行锁定,当分享资源使用完后。其它线程能力利用这些分享变量。那样就会制止race condition但会造成死锁。

同步(Synchronous) vs 异步(Asychronous)

那七个词是用来描写,被调用的函数在怎么时候将调整权再次来到给调用者。

一块:被调用的函数只会在实行完才将调整权给回调用者。异步:被调用的函数会立时将调整权重回给调用者,不管函数是或不是施行完。由此异步函数不会拥塞当前经过。

比如说以下代码:同步

override func viewDidLoad() { super.viewDidLoad() dispatch_sync(dispatch_get_global_queue( Int(QOS_CLASS_USER_INTERACTIVE.value), 0)) { NSLog("First Log") } NSLog("Second Log")}

bb电子糖果派对 4dispatch_sync_in_action_swift.gif

职务viewDidLoad会暂停等同步sync里面包车型大巴职责实行完再持续下一行代码。

异步

override func viewDidLoad() { super.viewDidLoad() dispatch_async(dispatch_get_global_queue( Int(QOS_CLASS_USER_INTERACTIVE.value), 0)) { NSLog("First Log") } NSLog("Second Log")}

bb电子糖果派对 5dispatch_async_in_action_swift.gif

如图,任务viewDidLoad不等待异步asyn里面包车型大巴代码职务施行完,就直接开首下一行代码

bb电子糖果派对 6

危险代码段(Critical Section卡塔尔

那是一段无法并发实行的代码。也正是无法被三个线程同不时间举办。例如:这段代码是因为校订分享的能源比如,只要四十八线程运营会立即崩溃。

//串行队列dispatch_queue_create("com.starming.serialqueue", DISPATCH_QUEUE_SERIAL)//并行队列dispatch_queue_create("com.starming.concurrentqueue", DISPATCH_QUEUE_CONCURRENT)

两个线程等待着互相的成就而深陷的窘境称为死锁。

线程安全

能被多少个线程同不日常候实施的能源

  • 联合异步线程创制
void swap{ lock; lock; int a = A; int b = B; A = b; B = a; unlock; unlock;}swap; // 线程 thread 1swap; // 线程 thread 2

资源竞争(race condition卡塔尔(قطر‎

bb电子糖果派对 7race-condition@2x-8b11b31d.png

如图,有一个变量存款和储蓄着17,然后线程A读取变量得到17,线程B也读取了这几个变量。四个线程都進展了加1运算得,并写入18都变量。进而招致了崩溃。那正是race condition,多线程使用分享能源,而并未有保险其余线程是现已甘休使用共享财富。

结果就能以致X被线程1锁住,Y被线程2锁住。而线程1又不能接纳Y直到线程2解锁,同理,线程2也不能够使用X。那正是死锁,相互等待。

相互之间消亡(Mutual ExclusionState of Qatar

bb电子糖果派对 8locking@2x-f425450b.png

如图,使用锁对线程正在使用的分享能源进行锁定,当分享财富使用完后。其余线程技艺接受这一个分享变量。那样就能够制止race condition但会导致死锁。

//同步线程dispatch_sync(..., ^//异步线程dispatch_async(..., ^

事前顺序颠倒难题,是由低权限任务的堵截着高权力职务的实践。进而让各种颠倒。

死锁

bb电子糖果派对 9dead-lock@2x-b45f0acd.png

八个线程等待着相互的实现而沦为的困境称为死锁。

void swap{ lock; lock; int a = A; int b = B; A = b; B = a; unlock; unlock;}swap; // 线程 thread 1swap; // 线程 thread 2

结果就能够导致X被线程1锁住,Y被线程2锁住。而线程1又无法接受Y直到线程2解锁,同理,线程2也无法使用X。那便是死锁,相互等待。

  • Serial:又叫private dispatch queues,同有时常候只实行八个任务。Serial queue常用于协同访问特定的能源或数额。当您创制三个Serial queue时,即便个别是一道,但serial queue之间是出新实行。
  • Main dispatch queue:全局可用的serial queue,在应用程序主线程上举办职分。
  • Concurrent:又叫global dispatch queue,可以现身的实行多少个职分,但实践到位顺序是随意的。系统提供两个全局并发队列,那多个系列有那对应的优先级,客商是不可以知道创制全局队列的,只好获得。

bb电子糖果派对 10

预先顺序颠倒(Priority Inversion卡塔尔

优先顺序颠倒难点,是由低权限职务的短路着高权力职分的进行。从而让种种颠倒。

bb电子糖果派对 11priority-inversion@2x-72e6760c.png

若是低权限的线程和高权力的线程使用分享财富。本应当,低权限的线程职分使用完分享能源后高权力的线程义务就能够没有延迟地进行。

但由于一方始高权力的线程因为低线程的锁而饱受梗塞。所以就给了空子中权限的线程职分,因为后天高权力受阻,所以中权限的线程任务是权力最高的,所以中权限职务中断低权限的线程职责的试行。进而让低线程的锁解不开,高线程职责也就延期试行。进而优先顺序颠倒。

就此在采纳GCD的时候,最佳将三十十二线程的职务施行优先权限保持一致。

假诺低权限的线程和高权力的线程使用分享财富。本应有,低权限的线程任务使用完分享财富后高权力的线程职务就会未有延迟地实行。但出于一齐首高权力的线程因为低线程的锁而惨被拥塞。所以就给了机会中权限的线程职务,因为前日高权力受阻,所以中权限的线程任务是权力最高的,所以中权限任务中断低权限的线程职务的进行。进而让低线程的锁解不开,高线程职责也就延迟执行。从而优先顺序颠倒。所以在运用GCD的时候,最棒将多线程的任务实施优先权限保持一致。

bb电子糖果派对,队列

GCD提供dispatch queue来管理提交的任务。那个队列管理你付出给GCD的职务并且根据FIFO的依次奉行。

dispatch queue都以线程安全的所以能够在七个线程里还要利用它们。

bb电子糖果派对 12Serial-Queue-Swift-480x272.png

串行队列只好一遍举办一个任务。如图,串行队列会一个紧挨着叁个地实施职务,正是二个扫尾另四个技能起首。

bb电子糖果派对 13Concurrent-Queue-Swift-480x272.png

并发队列里的任务是以步向队列的次第试行的,但你不明确职务什么日期完毕,几时初叶下三个义务。这取决GCD。

如图:职务0,1,2,3的起头是有种种的。但同一时间内足以有四个职责运转。

dipatch_queue_t queue;queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);

苹果程序猿在swift-dev邮件列表中钻探weak属性的线程安全难题的邮件里暴光自旋锁有bug,邮件地址:

队列类型(Queue Types卡塔尔(قطر‎

率先,系统提供了个特效的行列main queue,

main queue是串行队列,所以三回只可以进行四个任务。但以此队列是独步一时一个能用来更新UI和殡葬通知的行列。

系统也同偶尔候提供了多少个并发队列。这几个队列与自身的QOS等第有关,使得GCD能够调整优先级。

  • QOS_CLASS_USER_INTERACTIVE
  • QOS_CLASS_USER_INITIATED
  • QOS_CLASS_UTILITY
  • QOS_CLASS_BACKGROUND

Apples的API也会调用这个global dispatch queues,所以您增加的职分不会是队列里独一的职分。

除了以上5种队列外,你还足以创建队列。

  • user create queue:创造和睦定义的系列,能够用dispatch_queue_create函数,函数有多少个参数,第一个自定义的队列名,第四个参数是队列类型,暗中认可NULL或然DISPATCH_QUEUE_SECR-VIAL的是串行,参数为DISPATCH_QUEUE_CONCU宝马X5RENT为并行队列。

QOS服务等第

队列服务品级指的是早期级的抽象,针没错是在系统财富出现角逐或许是高品质负荷的情状下,遵照服务等级动态调解财富分配,对于使用GCD的开拓者来讲,预先将次第中的队列进行劳动品级的剪切和拘押,将急需张开实行的职责依据劳动等级次序划分,则能够越来越好的运用体系智能调整能源的特征。举例,响应客户对须求的义务、无须等待的后台职责、须求长日子且高质量保险的天职等等。

//创建QOS服务等级的队列 dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_USER_INTERACTIVE, QOS_MIN_RELATIVE_PRIORITY); dispatch_queue_t concurrent_queue = dispatch_queue_create("concurrent_queue.com", attr); dispatch_async(concurrent_queue, ^{ NSLog(@"concurrent_queue task exc"); });

QOS服务品级如下:

/*QOS_CLASS_USER_INTERACTIVE:user interactive等级表示任务需要被立即执行提供好的体验,用来更新UI,响应事件等。这个等级最好保持小规模。QOS_CLASS_USER_INITIATED:user initiated等级表示任务由UI发起异步执行。适用场景是需要及时结果同时又可以继续交互的时候。QOS_CLASS_UTILITY:utility等级表示需要长时间运行的任务,伴有用户可见进度指示器。经常会用来做计算,I/O,网络,持续的数据填充等任务。这个任务节能。QOS_CLASS_BACKGROUND:background等级表示用户不会察觉的任务,使用它来处理预加载,或者不需要用户交互和对时间不敏感的任务。*/__QOS_ENUM(qos_class, unsigned int, QOS_CLASS_USER_INTERACTIVE __QOS_CLASS_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x21, QOS_CLASS_USER_INITIATED __QOS_CLASS_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x19, QOS_CLASS_DEFAULT __QOS_CLASS_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x15, QOS_CLASS_UTILITY __QOS_CLASS_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x11, QOS_CLASS_BACKGROUND __QOS_CLASS_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x09, QOS_CLASS_UNSPECIFIED __QOS_CLASS_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x00,);

从服务类型这些维度区分,恐怕会将本应当串行实行只怕是并行实践的职分,却因服务类型不相同而切分差异的行列,比如,三个互连网央浼职分,八个心照不宣顾客事件的职分,本应有三个职责是串行试行的,但划分了不一致的QOS,导致放在三个串行队列中试行,那些五个义务就成并行职务了,解决这些主题材料能够运用安装指标队列。

防止read write问题

比方在三个单例里有犹如下属性,读和写

private var _photos: [Photo] = []//writefunc addPhoto(photo: Photo) { _photos.append}//readvar photos: [Photo] { return _photos}

可以保证线程安全的只有用let定义的。而数组,词典等用var定义的都不是线程安全的。

而地方的read和write都对变量数组举行更改使用。所以线程不安全。那怎么本领使其线程安全啊?

利用dispatch barriers实施read write lock

bb电子糖果派对 14Dispatch-Barrier-Swift-480x272.png

如图,dispatch barriers 能确定保障在它前边的task都进行完,在它之后的task 直到它成功前都无法实践也正是说在这里个task在它试行的每二十三日独占所在队列。

那么订正后的read write如下:

private var _photos: [Photo] = []//创建自定义并发队列private let concurrentPhotoQueue = dispatch_queue_create( "com.raywenderlich.GooglyPuff.photoQueue", DISPATCH_QUEUE_CONCURRENT) //writefunc addPhoto(photo: Photo) { dispatch_barrier_async(concurrentPhotoQueue) { self._photos.append }}//readvar photos: [Photo] { var photosCopy: [Photo]! dispatch_sync(concurrentPhotoQueue) { photosCopy = self._photos } return photosCopy}

write:

行使dispatch barriers,为啥创立自定义并发队列?

因为能够使用dispatch barriers有以下二种队列:

  • 自定义串行队列,因为串行队列本来便是一个职责一个任务地举办,所以用了等于没用。
  • 大局队列(Global Concurrent QueueState of Qatar,因为全局队列,Apples的API也使用,所以当使用dispatch barriers时,会拥塞队列。不建议选用
  • 自定义并发队列,只要并发队列里使用的是能源线程安全的。所以相比较提出。

read:接纳sync况兼跟write同一并发队列,因为那确定保证read和write是有种种的。进而幸免四线程的读写难题。

参照链接objc.io关于三十二线程或者招致的标题小说raywenderlich关于GCD使用的篇章

安装目的队列,划分队列等级次序

dispatch_queue_t targetQueue = dispatch_queue_create("test.target.queue", DISPATCH_QUEUE_SERIAL); //这三个队列可标记服务层级 dispatch_queue_t queue1 = dispatch_queue_create("test.1", DISPATCH_QUEUE_SERIAL); dispatch_queue_t queue2 = dispatch_queue_create("test.2", DISPATCH_QUEUE_SERIAL); dispatch_queue_t queue3 = dispatch_queue_create("test.3", DISPATCH_QUEUE_SERIAL); dispatch_set_target_queue(queue1, targetQueue); dispatch_set_target_queue(queue2, targetQueue); dispatch_set_target_queue(queue3, targetQueue); dispatch_async(queue1, ^{ NSLog; [NSThread sleepForTimeInterval:3.f]; NSLog; }); dispatch_async(queue2, ^{ NSLog; [NSThread sleepForTimeInterval:2.f]; NSLog; }); dispatch_async(queue3, ^{ NSLog; [NSThread sleepForTimeInterval:1.f]; NSLog; }); 
dispatch_queue_t queuequeue = dispatch_queue_create("com.starming.gcddemo.concurrentqueue", DISPATCH_QUEUE_CONCURRENT);

各样队列使用的气象

  • dispatch_get_main_queue(卡塔尔国-主队列:供给异进入UI主线程提交职分或队列中有任务到位需求更新UI时,dispatch_after在这里系列型中动用,无法合营交付大概是提交堵塞任务。
  • 自定义顺序队列:顺序试行后台职务并跟踪它时。那样做何况只有一个职务在实行可避防止财富竞争。dipatch barriers解决读写锁难题的放在这里随地理。dispatch groups也是放在这里处。
  • 并发队列:用来实施与UI毫不相关的后台任务,dispatch_sync放在这里处,方便等待任务成功进展一而再管理或和dispatch barrier同步。dispatch groups放在那处也对的。
dispatch_apply(100000, dispatch_queue_create(DISPATCH_CURRENT_QUEUE_LABEL, NULL), ^ { NSLog; });

dispatch_apply相同于for循环,循环体的逻辑可放在并发队列中并行实践,可加速for循环速度,但切莫滥用,因为GCD理论上可并发成立64条线程,当并发队列实践超多任务时,dispatch_apply提交到并发队列的动作则会堵塞其所在线程。

-(NSString *)name{ __block NSString * localName ; dispatch_sync(_t, ^{ localName = _name; }); return localName;}-setName:(NSString *)name{ dispatch_sync(_t, ^{ _name = name; });}self.t =dispatch_queue_create("com.topic-gcd.com", DISPATCH_QUEUE_SERIAL); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ self.name = @"111"; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ NSLog(@"%@",self.name); });

- (NSString *)name1{ __block NSString * localName1; dispatch_sync(_t, ^{ for (int i = 0; i<10000; i++) { } localName1 = _name1; }); return localName1;}-setName1:(NSString *)name1{ dispatch_async(_t, ^{ _name1 = name1; });}NSDate * date = [NSDate date]; self.name = @"222"; NSLog(@"%@",self.name); NSLog(@"name----%f",[NSDate date].timeIntervalSinceNow - date.timeIntervalSinceNow); date = [NSDate date]; self.name1 = @"111"; NSLog(@"%@",self.name1); NSLog(@"name1----%f",[NSDate date].timeIntervalSinceNow - date.timeIntervalSinceNow);

结果如下:

2017-04-11 13:33:45.512 topic-gcd[52228:4492576] 2222017-04-11 13:33:45.513 topic-gcd[52228:4492576] name----0.0003902017-04-11 13:33:45.513 topic-gcd[52228:4492576] 1112017-04-11 13:33:45.513 topic-gcd[52228:4492576] name1----0.000198

- setName2:(NSString *)name2{ dispatch_barrier_async(self.t, ^{ _name2 = name2; });}- (NSString *)name2{ __block NSString * localName2; dispatch_sync(self.t, ^{ for (int i = 0; i<1000000; i++) { } localName2 = _name2; }); return localName2;}//使用并行队列,读操作异步执行,写操作同步执行 self.t = dispatch_queue_create(DISPATCH_CURRENT_QUEUE_LABEL, NULL); self.name2 = @"33"; NSLog(@"1.read name2---->%@",self.name2); NSLog(@"2.read name2---->%@",self.name2); NSLog(@"3.read name2---->%@",self.name2); self.name2 = @"333"; NSLog(@"4.read name2---->%@",self.name2); NSLog(@"5.read name2---->%@",self.name2); NSLog(@"6.read name2---->%@",self.name2);
  • 自定义队列的初期级:能够因此dipatch_queue_attr_make_with_qos_class或dispatch_set_target_queue方法设置队列的优先级

dispatch_barrier_async为何切合采纳在自定义并发队列呢?

  1. 串行队列本来正是三个职责叁个职务地串行执行,毫无意义
  2. 大局队列(Global Concurrent Queue卡塔尔(قطر‎,因为全局队列超多地方在用,包罗系统的API也在用,使用dispatch_barrier_async能够隔断此行列,所以不建议选拔
  3. 自定义并发队列,只要并发队列里使用的是财富线程安全的。所以相比提出

Dispatch Group将区别队列设置为一个group,能够使用dispatch_group_wait设置梗塞点,等待整个组内的异步任务到位,恐怕是选拔dispatch_group_notify异步试行到位组内职分的回调,进而不打断当前线程。注意,group中只要增加主队列再采用dispatch_group_wait有希望孳生死锁。

//使用Dispatch Group,并发队列异步执行任务 dispatch_group_t group = dispatch_group_create(); //在主线程队列中执行 dispatch_group_async(group, dispatch_get_main_queue(), ^{ NSLog; }); //在创建的一个并行队列中执行 dispatch_group_async(group, self.t, ^{ NSLog; }); //在全局队列中执行 dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog; }); //死锁// dispatch_group_wait(group, DISPATCH_TIME_FOREVER);// NSLog; //在主线程队列中监听所有任务执行完毕的回调 dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog; });

使用dispatch_group_enter与dispatch_group_leave合併异步任务组

对于一些异步职务,想要利用职责组来治本到达监听落成回调也许是拥塞当前线程举办线程同步,则足以行使dispatch_group_enter与dispatch_group_leave,例子如下:

//使用dispatch_group_enter与dispatch_group_leave合并异步任务组 dispatch_group_t block_group = dispatch_group_create(); dispatch_group_enter(block_group); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog; dispatch_group_leave(block_group); }); dispatch_group_enter(block_group); dispatch_async(dispatch_get_main_queue(), ^{ NSLog; dispatch_group_leave(block_group); }); dispatch_group_notify(block_group, dispatch_get_main_queue(), ^{ NSLog(@"异步任务1和任务2全部完成"); });

虽说异步任务1与异步任务2是莫衷一是门类的类别之中的职务,但足以由此enter与leave来达到将多少个职分进展职务组编排,比如说三个分界面须求等待七个接口调用全部成就才可以带头化,除了早先设置哨兵变量以外,还可以运用方面包车型客车办法来开展任务编排。在行使CoreData的时候就可以将异步数据库操作变成职分组。

dispatch_group_enter;[self.context performBlock:^(){ //some core data actions dispatch_group_leave;}];

亟待潜心的是:dispatch_group_async等价于dispatch_group_enter() 和 dispatch_group_leave()的组合。dispatch_group_enter(卡塔尔国 必需运营在 dispatch_group_leave() 之前。dispatch_group_enter() 和 dispatch_group_leave(卡塔尔 要求成对现身的

//dispatch_block_wait使用dispatch_queue_t block_serialQueue = dispatch_queue_create("com.block_serialQueue.com", DISPATCH_QUEUE_SERIAL);dispatch_block_t block = dispatch_block_create(0, ^{ [NSThread sleepForTimeInterval:5.f]; NSLog(@"block_serialQueue block end");});dispatch_async(block_serialQueue, block);//设置DISPATCH_TIME_FOREVER会一直等到前面任务都完成dispatch_block_wait(block, DISPATCH_TIME_FOREVER);block = dispatch_block_create(0, ^{ NSLog(@"second block_serialQueue block end");});dispatch_async(block_serialQueue, block);dispatch_block_notify(block, dispatch_get_main_queue(), ^{ NSLog(@"block_serialQueue block finished");});

当某一个异步任务block,须要监听其是还是不是做到,能够选用wait与notify来简化代码逻辑。举例,可应用该本性,来组合异步职务的实施各样吧,重假如本着已存在的异步任务逻辑代码。比如说,可将互连网乞求的异步职责扩充串联。

能够接收group与dispatch_block_cancel将一组编排好的异步职责组中的异步义务进展撤消,比如说在有些视图调整器中,发起了N个互联网诉求,离开分界面包车型大巴时候,倘若互联网须要未有任何截至,而客户退出该分界面,则足以收回这一个异步职务回笼线程财富,简单完毕如下:

 //使用Dispatch Group与dispatch_block_cancel,取消异步任务 NSMutableArray * request_blocks = [NSMutableArray array]; dispatch_group_t request_blocks_group = dispatch_group_create(); //开启五个异步网络请求任务 for (int i = 0; i<5; i++) { dispatch_block_t request_block = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{ NSURLRequest * request = [[NSURLRequest alloc]init]; dispatch_group_enter(request_blocks_group); [self postWithRequest:request completion:^(id responseObjecy, NSURLResponse *response, NSError *error) { //do somethings dispatch_group_leave(request_blocks_group); }]; }); [request_blocks addObject:request_block]; dispatch_async(dispatch_get_main_queue(), request_block); } //取消这五个任务 for (dispatch_block_t request_block in request_blocks) { dispatch_block_cancel(request_block); dispatch_group_leave(request_blocks_group); } dispatch_group_notify(request_blocks_group, dispatch_get_main_queue(), ^{ NSLog(@"网络任务请求执行完毕或者全部取消"); });

//dispatch_io_t的使用 NSString * plist_path = [[NSBundle mainBundle]pathForResource:@"Info" ofType:@".plist"];//获取文件dispatch_fd_t 的描述符 dispatch_fd_t fd = open(plist_path.UTF8String, O_RDONLY);//创建文件读取所使用的操作队列 dispatch_queue_t queue = dispatch_queue_create("test io", NULL);//根据描述符创建GCD的读取流 dispatch_io_t pipe_channel = dispatch_io_create(DISPATCH_IO_STREAM, fd, queue, ^(int error) { close;//设置读取大小 dispatch_io_set_low_water(pipe_channel, SIZE_MAX);//使用文件流来读取内容 dispatch_io_read(pipe_channel, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t _Nullable data, int error) { if  { } if  { } size_t len = dispatch_data_get_size; if  { } });

GCD个中有关io读取的API极其丰裕,利用unix风格的io函数来开展文件操作,与队列进行协作,可获取GCD自动调整财富利用四线程实行io操作的力量,同期前边提到的种种异步拥塞也许联合的模型可以采用,创制一套高效的io操作,知足大文件读取的高品质供给。

//dipatch_queue_attr_make_with_qos_classdispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, -1);dispatch_queue_t queue = dispatch_queue_create("com.starming.gcddemo.qosqueue", attr);//dispatch_set_target_queuedispatch_queue_t queue = dispatch_queue_create("com.starming.gcddemo.settargetqueue",NULL); //需要设置优先级的queuedispatch_queue_t referQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); //参考优先级dispatch_set_target_queue(queue, referQueue); //设置queue和referQueue的优先级一样
  • dispatch_set_target_queue:能够安装优先级,也足以安装队列层级类别,比方让八个串行和相互队列在集合三个串行队列里串行施行,如下
dispatch_queue_t serialQueue = dispatch_queue_create("com.starming.gcddemo.serialqueue", DISPATCH_QUEUE_SERIAL);dispatch_queue_t firstQueue = dispatch_queue_create("com.starming.gcddemo.firstqueue", DISPATCH_QUEUE_SERIAL);dispatch_queue_t secondQueue = dispatch_queue_create("com.starming.gcddemo.secondqueue", DISPATCH_QUEUE_CONCURRENT);dispatch_set_target_queue(firstQueue, serialQueue);dispatch_set_target_queue(secondQueue, serialQueue);dispatch_async(firstQueue, ^{ NSLog; [NSThread sleepForTimeInterval:3.f];});dispatch_async(secondQueue, ^{ NSLog; [NSThread sleepForTimeInterval:2.f];});dispatch_async(secondQueue, ^{ NSLog; [NSThread sleepForTimeInterval:1.f];});

队列私下认可是串行的,如若设置改参数为NULL会按串行管理,只好实行多少个单身的block,队列也足以是互为的,同期推行八个block

- init;{ self = [super init]; if (self != nil) { NSString *label = [NSString stringWithFormat:@"%@.isolation.%p", [self class], self]; self.isolationQueue = dispatch_queue_create([label UTF8String], 0); label = [NSString stringWithFormat:@"%@.work.%p", [self class], self]; self.workQueue = dispatch_queue_create([label UTF8String], 0); } return self;}

5种队列,主队列(main queue),八种通用调解队列,本身定制的系列。种种通用调节队列为

  • QOS_CLASS_USER_INTERACTIVE:user interactive等级表示职责需求被立刻实践提供好的经验,用来更新UI,响应事件等。那一个品级最棒保持小框框。
  • QOS_CLASS_USER_INITIATED:user initiated品级表示使命由UI发起异步实施。适用处景是亟需立即结果同偶尔间又足以世襲相互的时候。
  • QOS_CLASS_UTILITY:utility等第表示必要长日子运作的任务,伴有客商可以知道进程提示器。平时会用来做总结,I/O,网络,持续的数量填充等职分。这一个职务节约财富。
  • QOS_CLASS_BACKGROUND:background等第表示客户不会意识的职分,使用它来管理预加载,可能无需客户人机联作和对时间不灵动的职责。

演示:后台加载显示图片

override func viewDidLoad() { super.viewDidLoad() dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) { // 将工作从主线程转移到全局队列中,这是dispatch_async调用,异步提交保证调用线程会继续执行下去,这样viewDidLoad在主线程上能够更早完成, let overlayImage = self.faceOverlayImageFromImage(self.image) dispatch_async(dispatch_get_main_queue { // 新图完成,把一个闭包加入主线程用来更新UIImageView,只有在主线程能操作UIKit。 self.fadeInNewImage(overlayImage) // 更新UI } }}

什么日期使用何种队列类型

  • 主队列:队列中有职责到位必要更新UI时,dispatch_after在此连串型中使用。
  • 并发队列:用来举办与UI毫不相关的后台职责,dispatch_sync放在那,方便等待职务成功进展后续管理或和dispatch barrier同步。dispatch groups放在此也不利。
  • 自定义顺序队列:顺序实践后台职责并追踪它时。那样做並且唯有三个职务在推行可防止范能源角逐。dipatch barriers撤销读写锁难题的放在这里随处理。dispatch groups也是放在那。

能够动用上边包车型客车艺术简化QoS等第参数的写法

var GlobalMainQueue: dispatch_queue_t { return dispatch_get_main_queue()}var GlobalUserInteractiveQueue: dispatch_queue_t { return dispatch_get_global_queue(Int(QOS_CLASS_USER_INTERACTIVE.value), 0)}var GlobalUserInitiatedQueue: dispatch_queue_t { return dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)}var GlobalUtilityQueue: dispatch_queue_t { return dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)}var GlobalBackgroundQueue: dispatch_queue_t { return dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0)}//使用起来就是这样,易读而且容易看出在使用哪个队列dispatch_async(GlobalUserInitiatedQueue) { let overlayImage = self.faceOverlayImageFromImage(self.image) dispatch_async(GlobalMainQueue) { self.fadeInNewImage(overlayImage) }}

dispatch_once_t要是大局或static变量,保险dispatch_once_t只有一份实例

+ (UIColor *)boringColor;{ static UIColor *color; //只运行一次 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ color = [UIColor colorWithRed:0.380f green:0.376f blue:0.376f alpha:1.000f]; }); return color;}

统筹叁个异步的API调用dispatch_async(卡塔尔,那些调用放在API的不二秘籍或函数中做。让API的使用者设置贰个回调解和管理理队列

- processImage:(UIImage *)image completionHandler:(BOOL success))handler;{ dispatch_async(self.isolationQueue, ^{ // do actual processing here dispatch_async(self.resultQueue, ^{ handler; });}

能够免止分界面会被一些耗费时间的操作卡死,比方读取网络数据,大额IO,还应该有大量数目标数据库读写,当时需求在另一个线程中拍卖,然后公告主线程更新分界面,GCD使用起来比NSThread和NSOperation方法要轻巧方便。

//代码框架dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 耗时的操作 dispatch_async(dispatch_get_main_queue(), ^{ // 更新界面 });});//下载图片的示例dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSURL * url = [NSURL URLWithString:@"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"]; NSData * data = [[NSData alloc]initWithContentsOfURL:url]; UIImage *image = [[UIImage alloc]initWithData:data]; if (data != nil) { dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = image; }); }});

下一篇:没有了
友情链接: 网站地图
Copyright © 2015-2019 http://www.tk-web.com. bb电子糖果派对有限公司 版权所有