1、問題:執(zhí)行任務(wù)1、2;再執(zhí)行3、4有哪些方法?
-
dispatch_barrier_阻塞隊(duì)列
使用dispatch_barrier_ 的時(shí),要主要兩點(diǎn)一點(diǎn)隊(duì)列必須是自定義的隊(duì)列,并且是并發(fā)隊(duì)列;dispatch_get_global(0,0)不行
dispatch_queue_t myQueue = dispatch_queue_create("myqueue",DISPATCH_QUEUE_CONCURRENT);
NSLog(@"先頭任務(wù)");
dispatch_async(myQueue,^{
NSLog(@"當(dāng)前線程%p==任務(wù)1",[NSThread currentThread]);
});
dispatch_async(myQueue,^{
NSLog(@"當(dāng)前線程%p==任務(wù)2",[NSThread currentThread]);
});
NSLog(@"pre barrier");
dispatch_barrier_async(myQueue, ^{
NSLog(@"當(dāng)前線程%p==阻塞隊(duì)列myQueue",[NSThread currentThread]);
});
NSLog(@"后續(xù)任務(wù)");
dispatch_async(myQueue,^{
NSLog(@"當(dāng)前線程%p==任務(wù)3",[NSThread currentThread]);
});
dispatch_async(myQueue,^{
NSLog(@"當(dāng)前線程%p==任務(wù)4",[NSThread currentThread]);
});
打印結(jié)果

image.png
dispatch_queue_t myQueue = dispatch_queue_create("myqueue",DISPATCH_QUEUE_CONCURRENT);
NSLog(@"先頭任務(wù)");
dispatch_async(myQueue,^{
NSLog(@"當(dāng)前線程%p==任務(wù)1",[NSThread currentThread]);
});
dispatch_async(myQueue,^{
NSLog(@"當(dāng)前線程%p==任務(wù)2",[NSThread currentThread]);
});
NSLog(@"pre barrier");
dispatch_barrier_sync(myQueue, ^{
NSLog(@"當(dāng)前線程%p==阻塞隊(duì)列myQueue",[NSThread currentThread]);
});
NSLog(@"后續(xù)任務(wù)");
dispatch_async(myQueue,^{
NSLog(@"當(dāng)前線程%p==任務(wù)3",[NSThread currentThread]);
});
dispatch_async(myQueue,^{
NSLog(@"當(dāng)前線程%p==任務(wù)4",[NSThread currentThread]);
});
打印信息

image.png
dispatch_barrier_async不會(huì)阻塞當(dāng)前線程;
dispatch_barrier_sync會(huì)卡住當(dāng)前線程;
diapatch_group_queue
1、dispatch_group_create創(chuàng)建一個(gè)調(diào)度任務(wù)組
2、dispatch_group_async 把一個(gè)任務(wù)異步提交到任務(wù)組里
3、dispatch_group_enter/dispatch_group_leave 這種方式用在不使用dispatch_group_async來提交任務(wù),且必須配合使用
4、dispatch_group_notify 用來監(jiān)聽任務(wù)組事件的執(zhí)行完畢
5、dispatch_group_wait 設(shè)置等待時(shí)間,在等待時(shí)間結(jié)束后,如果還沒有執(zhí)行完任務(wù)組,則返回。返回0代表執(zhí)行成功,非0則執(zhí)行失敗
場景1:
現(xiàn)在有4個(gè)任務(wù),任務(wù)1、任務(wù)2、任務(wù)3、任務(wù)4. 任務(wù)3必須在任務(wù)2之后,任務(wù)4必須在前3個(gè)任務(wù)都執(zhí)行完成后,才能執(zhí)行,并且需要在主線程更新UI。
思路分析:
任務(wù)3必須在任務(wù)2之后,所以這兩個(gè)必須串行執(zhí)行,同時(shí),任務(wù)2和3整體可以和任務(wù)1并行執(zhí)行,最后,任務(wù)4只能等待前3個(gè)任務(wù)全部執(zhí)行完成,才能執(zhí)行。這里就可以用group快速實(shí)現(xiàn)場景需求。
dispatch_queue_t c_Queue = dispatch_queue_create("myqueue",DISPATCH_QUEUE_CONCURRENT);//并發(fā)隊(duì)列
dispatch_queue_t s_Queue = dispatch_queue_create("myqueue",DISPATCH_QUEUE_SERIAL);//串行隊(duì)列
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, c_Queue, ^{
NSLog(@"任務(wù)1");
});
dispatch_group_async(group, s_Queue, ^{
NSLog(@"任務(wù)2");
});
dispatch_group_async(group, s_Queue, ^{
NSLog(@"任務(wù)3");
});
dispatch_group_async(group, dispatch_get_main_queue(), ^{
NSLog(@"任務(wù)4");
});

image.png
其中3始終在2的后面,1的位置始終在4前面,4在最后。
-
dispatch_semaphore信號(hào)量:就是一種可用來控制訪問資源的數(shù)量的標(biāo)識(shí),設(shè)定了一個(gè)信號(hào)量,在線程訪問之前,加上信號(hào)量的處理,則可告知系統(tǒng)按照我們指定的信號(hào)量數(shù)量來執(zhí)行多個(gè)線程。
假設(shè)現(xiàn)在系統(tǒng)有兩個(gè)空閑資源可以被利用,但同一時(shí)間卻有三個(gè)線程要進(jìn)行訪問,這種情況下,該如何處理呢?
dispatch_semaphore_create(long value); // 創(chuàng)建信號(hào)量
dispatch_semaphore_signal(dispatch_semaphore_t deem); // 發(fā)送信號(hào)量
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); // 等待信號(hào)量
// 創(chuàng)建信號(hào)量
dispatch_semaphore_t sem = dispatch_semaphore_create(1);
dispatch_queue_t c_Queue = dispatch_queue_create("myqueue",DISPATCH_QUEUE_CONCURRENT);//并發(fā)隊(duì)列
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_async(c_Queue, ^{
sleep(1);
NSLog(@"任務(wù)1");
});
dispatch_async(c_Queue, ^{
NSLog(@"任務(wù)2");
dispatch_semaphore_signal(sem);
});
// 等待信號(hào)量 超時(shí)時(shí)間 -1 sem 小于0就會(huì)阻塞
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_async(c_Queue, ^{
NSLog(@"任務(wù)3");
dispatch_semaphore_signal(sem);
});
-
NSOperition
NSOperation、NSOperationQueue 常用屬性和方法歸納
1、NSOperation 常用屬性和方法
取消操作方法
- (void)cancel;可取消操作,實(shí)質(zhì)是標(biāo)記 isCancelled 狀態(tài)。
判斷操作狀態(tài)方法 - (BOOL)isFinished;判斷操作是否已經(jīng)結(jié)束。
- (BOOL)isCancelled;判斷操作是否已經(jīng)標(biāo)記為取消。
- (BOOL)isExecuting;判斷操作是否正在在運(yùn)行。
- (BOOL)isReady;判斷操作是否處于準(zhǔn)備就緒狀態(tài),這個(gè)值和操作的依賴關(guān)系相關(guān)。
操作同步 - (void)waitUntilFinished;阻塞當(dāng)前線程,直到該操作結(jié)束。可用于線程執(zhí)行順序的同步。
- (void)setCompletionBlock:(void (^)(void))block;completionBlock會(huì)在當(dāng)前操作執(zhí)行完畢時(shí)執(zhí)行 completionBlock。
- (void)addDependency:(NSOperation *)op;添加依賴,使當(dāng)前操作依賴于操作 op 的完成。
- (void)removeDependency:(NSOperation *)op;移除依賴,取消當(dāng)前操作對(duì)操作 op 的依賴。
@property (readonly, copy) NSArray<NSOperation *> *dependencies;在當(dāng)前操作開始執(zhí)行之前完成執(zhí)行的所有操作對(duì)象數(shù)組。
2、NSOperationQueue常用屬性和方法
取消/暫停/恢復(fù)操作
- (void)cancelAllOperations;可以取消隊(duì)列的所有操作。
- (BOOL)isSuspended;判斷隊(duì)列是否處于暫停狀態(tài)。 YES 為暫停狀態(tài),NO 為恢復(fù)狀態(tài)。
- (void)setSuspended:(BOOL)b;可設(shè)置操作的暫停和恢復(fù),YES 代表暫停隊(duì)列,NO 代表恢復(fù)隊(duì)列。
操作同步 - (void)waitUntilAllOperationsAreFinished;阻塞當(dāng)前線程,直到隊(duì)列中的操作全部執(zhí)行完畢。
添加/獲取操作 - (void)addOperationWithBlock:(void (^)(void))block;向隊(duì)列中添加一個(gè) NSBlockOperation 類型操作對(duì)象。
- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait;向隊(duì)列中添加操作數(shù)組,wait 標(biāo)志是否阻塞當(dāng)前線程直到所有操作結(jié)束
- (NSArray *)operations;當(dāng)前在隊(duì)列中的操作數(shù)組(某個(gè)操作執(zhí)行結(jié)束后會(huì)自動(dòng)從這個(gè)數(shù)組清除)。
- (NSUInteger)operationCount;當(dāng)前隊(duì)列中的操作數(shù)。
獲取隊(duì)列
- (id)currentQueue;獲取當(dāng)前隊(duì)列,如果當(dāng)前線程不是在 NSOperationQueue 上運(yùn)行則返回 nil。
- (id)mainQueue;獲取主隊(duì)列。
不錯(cuò)的文章
https://blog.csdn.net/u011043997/article/details/86678771