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