dispatch_barrier_async ?函數(shù)的作用:如果任務(wù)是通過dispatch_barrier_async函數(shù)追加到concurrent queue中的,執(zhí)行該任務(wù)時(shí),其他的線程不執(zhí)行,直到該任務(wù)完成,才恢復(fù)執(zhí)行剩余的任務(wù).
創(chuàng)建并行隊(duì)列 : dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
創(chuàng)建串行隊(duì)列 :? dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", NULL); //DISPATCH_QUEUE_SERIAL
NSOperation 是蘋果公司對(duì) GCD 的封裝,完全面向?qū)ο螅允褂闷饋砀美斫狻?大家可以看到 NSOperation 和 NSOperationQueue 分別對(duì)應(yīng) GCD 的 任務(wù) 和 隊(duì)列 。
*1//1.創(chuàng)建NSInvocationOperation對(duì)象
NSInvocationOperation?*operation?=?[[NSInvocationOperation?alloc]?initWithTarget:self?selector:@selector(run)?object:nil];
//2.開始執(zhí)行
[operation?start];
*2//1.創(chuàng)建NSBlockOperation對(duì)象
NSBlockOperation?*operation?=?[NSBlockOperation?blockOperationWithBlock:^{
NSLog(@"%@",?[NSThread?currentThread]);
}];
//2.開始任務(wù)
[operation?start];
NSBlockOperation 還有一個(gè)方法:addExecutionBlock: ,通過這個(gè)方法可以給 Operation 添加多個(gè)執(zhí)行 Block。這樣 Operation 中的任務(wù) 會(huì)并發(fā)執(zhí)行,它會(huì) 在主線程和其它的多個(gè)線程 執(zhí)行這些任務(wù)
//1.創(chuàng)建一個(gè)其他隊(duì)列
NSOperationQueue?*queue?=?[[NSOperationQueue?alloc]?init];
//2.創(chuàng)建NSBlockOperation對(duì)象
NSBlockOperation?*operation?=?[NSBlockOperation?blockOperationWithBlock:^{
NSLog(@"%@",?[NSThread?currentThread]);
}];
//3.添加多個(gè)Block
for(NSInteger?i?=?0;?i?<?5;?i++)?{
[operation?addExecutionBlock:^{
NSLog(@"第%ld次:%@",?i,?[NSThread?currentThread]);
}];
}
//4.隊(duì)列添加任務(wù)
[queue?addOperation:operation];
OK, 這時(shí)應(yīng)該發(fā)問了,大家將 NSOperationQueue 與 GCD的隊(duì)列 相比較就會(huì)發(fā)現(xiàn),這里沒有并行隊(duì)列,那如果我想要10個(gè)任務(wù)在其他線程串行的執(zhí)行怎么辦?
這就是蘋果封裝的妙處,你不用管串行、并行、同步、異步這些名詞。NSOperationQueue 有一個(gè)參數(shù) maxConcurrentOperationCount 最大并發(fā)數(shù),用來設(shè)置最多可以讓多少個(gè)任務(wù)同時(shí)執(zhí)行。當(dāng)你把它設(shè)置為 1 的時(shí)候,他不就是串行了嘛!
NSOperationQueue 還有一個(gè)添加任務(wù)的方法,- (void)addOperationWithBlock:(void (^)(void))block; ,這是不是和 GCD 差不多?這樣就可以添加一個(gè)任務(wù)到隊(duì)列中了,十分方便
NSOperation 有一個(gè)非常實(shí)用的功能,那就是添加依賴。比如有 3 個(gè)任務(wù):A: 從服務(wù)器上下載一張圖片,B:給這張圖片加個(gè)水印,C:把圖片返回給服務(wù)器。這時(shí)就可以用到依賴了
operation2.addDependency(operation1) //添加依賴關(guān)系
NSOperation:
BOOL?executing;//判斷任務(wù)是否正在執(zhí)行
BOOL?finished;//判斷任務(wù)是否完成
void?(^completionBlock)(void);//用來設(shè)置完成后需要執(zhí)行的操作
-?(void)cancel;//取消任務(wù)
-?(void)waitUntilFinished;//阻塞當(dāng)前線程直到此任務(wù)執(zhí)行完畢
NSOperationQueue:
NSUInteger?operationCount;//獲取隊(duì)列的任務(wù)數(shù)
-?(void)cancelAllOperations;//取消隊(duì)列中所有的任務(wù)
-?(void)waitUntilAllOperationsAreFinished;//阻塞當(dāng)前線程直到此隊(duì)列中的所有任務(wù)執(zhí)行完畢
[queue?setSuspended:YES];//?暫停queue
[queue?setSuspended:NO];//?繼續(xù)queue
線程同步?
所謂線程同步就是為了防止多個(gè)線程搶奪同一個(gè)資源造成的數(shù)據(jù)安全問題,所采取的一種措施。當(dāng)然也有很多實(shí)現(xiàn)方法.
互斥鎖:給需要同步的代碼塊加一個(gè)互斥鎖,就可以保證每次只有一個(gè)線程訪問此代碼塊。
@synchronized(self) {
//需要執(zhí)行的代碼塊
}
同步執(zhí)行:我們可以使用多線程的知識(shí),把多個(gè)線程都要執(zhí)行此段代碼添加到同一個(gè)串行隊(duì)列,這樣就實(shí)現(xiàn)了線程同步的概念。當(dāng)然這里可以使用 GCD 和 NSOperation 兩種方案
//GCD
//需要一個(gè)全局變量queue,要讓所有線程的這個(gè)操作都加到一個(gè)queue中
dispatch_sync(queue,?^{
NSInteger?ticket?=?lastTicket;
[NSThread?sleepForTimeInterval:0.1];
NSLog(@"%ld?-?%@",ticket,?[NSThread?currentThread]);
ticket?-=?1;
lastTicket?=?ticket;
});
//NSOperation?&?NSOperationQueue
//重點(diǎn):1.?全局的?NSOperationQueue,?所有的操作添加到同一個(gè)queue中
//???????2.?設(shè)置?queue?的?maxConcurrentOperationCount?為?1
//???????3.?如果后續(xù)操作需要Block中的結(jié)果,就需要調(diào)用每個(gè)操作的waitUntilFinished,阻塞當(dāng)前線程,一直等到當(dāng)前操作完成,才允許執(zhí)行后面的。waitUntilFinished?要在添加到隊(duì)列之后!
NSBlockOperation?*operation?=?[NSBlockOperation?blockOperationWithBlock:^{
NSInteger?ticket?=?lastTicket;
[NSThread?sleepForTimeInterval:1];
NSLog(@"%ld?-?%@",ticket,?[NSThread?currentThread]);
ticket?-=?1;
lastTicket?=?ticket;
}];
[queue?addOperation:operation];
[operation?waitUntilFinished];
//后續(xù)要做的事
從其他線程回到主線程的方法:
1. [self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:NO];
2. dispatch_async(dispatch_get_main_queue(), ^{
});
3. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
}];