主隊(duì)列上的同步異步執(zhí)行
-
主隊(duì)列 異步執(zhí)行 在主線程有序執(zhí)行
dispatch_queue_t queue = dispatch_get_main_queue();
for (int i = 0; i < 10; i++) {dispatch_async(queue, ^{ NSLog(@"hello---%d %@",i,[NSThread currentThread]); }); }
-
主隊(duì)列 同步執(zhí)行 在主線程上執(zhí)行時(shí)會(huì)死鎖
dispatch_queue_t queue = dispatch_get_main_queue(); //測(cè)試執(zhí)行 NSLog(@"begin"); for (int i = 0; i < 10; i++) { dispatch_sync(queue, ^{ NSLog(@"hello --- %@",[NSThread currentThread]); }); } //測(cè)試執(zhí)行 NSLog(@"end");
分析
從運(yùn)行結(jié)果可以明顯看出刨秆,程序無(wú)法正常執(zhí)行 被死鎖。
接下來(lái)看一下鎖死的原因:
當(dāng)程序運(yùn)行到下面這段代碼時(shí)
<pre> dispatch_sync(queue, ^{
NSLog(@"hello --- %@",[NSThread currentThread]);
}); </pre>
主線程:如果主線程正在執(zhí)行行代碼图柏,就不調(diào)度任務(wù)
同步執(zhí)行: 如果第一個(gè)任務(wù)沒(méi)有執(zhí)行立哑,就等待第一個(gè)任務(wù)執(zhí)行完成后彤钟,在執(zhí)行下一個(gè)任務(wù)。導(dǎo)致程序互相等待,造成死鎖仆百。
解決方案
(主隊(duì)列 同步執(zhí)行)放入異步執(zhí)行糖权,解決死鎖問(wèn)題
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_queue_t queue1 = dispatch_get_global_queue(0, 0);
//測(cè)試執(zhí)行
NSLog(@"begin");
dispatch_async(queue1, ^{
for (int i = 0; i <10; i++) {
dispatch_sync(queue, ^{
NSLog(@"hello---%d %@",i,[NSThread currentThread]);
});
}
});
//測(cè)試執(zhí)行
NSLog(@"end");
知識(shí)拓展
主隊(duì)列于串行隊(duì)列的區(qū)別
- 串行隊(duì)列: 必須的一個(gè)任務(wù)調(diào)度完成堵腹,再去執(zhí)行另一個(gè)任務(wù)
- 主隊(duì)列: 以先進(jìn)先出的調(diào)度任務(wù),如果主線程上有任務(wù)在執(zhí)行星澳,主隊(duì)列不會(huì)調(diào)用任務(wù)
走進(jìn)NSOperation
NSOperation是一個(gè)抽象的類
- 不能直接使用(方法沒(méi)有實(shí)現(xiàn))
- 結(jié)束子類都具有共同的屬性和方法
NSOperation的子類
- NSInvocationOperation
- NSBlockOperation
- 自定義operation
NSOperationQueue隊(duì)列
-
NSInvocationOperation
新建一個(gè)NSInvocationOperation對(duì)象
- (id)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;
- 調(diào)用start方法開始執(zhí)行操作
- (void) start;
一旦執(zhí)行操作疚顷,就回到用start 的sel方法
注意
默認(rèn)情況下,調(diào)用start方法并不會(huì)開一條新線程執(zhí)行操作禁偎,而是在當(dāng)前線程同步執(zhí)行操作腿堤,只有將一個(gè)NSOperation放到NSOperationQueue中,才會(huì)異步執(zhí)行操作
接下來(lái)我們來(lái)測(cè)試一下
- (void)viewDidLoad {
[super viewDidLoad];
//NSInvocationOperation操作
//創(chuàng)建操作
NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(diown) object:nil];
//創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//異步執(zhí)行
[queue addOperation:operation];
//同步執(zhí)行
}
-(void) diown{
NSLog(@"download --- %@",[NSThread currentThread]);
}
可以看出如暖,在子線程中執(zhí)行的笆檀。如果沒(méi)有將NSOperation放到NSOperationQueue中,將會(huì)同步執(zhí)行装处,這里不做演示了
-
NSBlockOperation
新建一個(gè) NSBlockOperation對(duì)象
+ (instancetype)blockOperationWithBlock:(void (^)(void))block;
*創(chuàng)建addExecutionBlock:方法添加更多操作
- (void)addExecutionBlock:(void (^)(void))block;
注意
只要NSBlockOperation封裝的操作 >1 就會(huì)執(zhí)行误债,異步操作
接下來(lái)我們來(lái)測(cè)試一下
NSBlockOperation *operation = [[NSBlockOperation alloc]init];
[operation addExecutionBlock:^{
NSLog(@"----下載圖片--1---%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"----下載圖片--2---%@",[NSThread currentThread]);
}];
[operation start];
-
NSOperationQueue
NSOperationQueue的作用
NSOperation可以調(diào)用start方法來(lái)調(diào)用任務(wù),但是默認(rèn)是同步執(zhí)行妄迁。如果將NSOperation添加到NSOperationQueue的隊(duì)列中寝蹈,系統(tǒng)會(huì)自動(dòng),異步執(zhí)行
添加操作到NSOperationQueue中
- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block ;
下面將演示這兩種不同的添加方式
- 第一種
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(deom) object:nil];
[op start];
[queue addOperation:op];
- (void) demo{
NSLog(@"%@",[NSThread currentThread]);
}
- 第二種(創(chuàng)建全程隊(duì)列)--相比第一種登淘,這一種更為簡(jiǎn)便
@interface ViewController ()
//創(chuàng)建一個(gè)全程隊(duì)列
@property (nonatomic, strong) NSOperationQueue *queue;
@end
//懶加載
- (NSOperationQueue *)queue{
if (_queue == nil) {
_queue = [[NSOperationQueue alloc]init];
}
return _queue;
}
[self.queue addOperationWithBlock:^{
NSLog(@"qqq %@",[NSThread currentThread]);
NSLog(@"下載圖片");
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"回到主線程");
NSLog(@"%@",[NSThread currentThread]);
}];
}];