GCD的同步異步串行并行、NSOperation和NSOperationQueue一級用dispatch_once實現單例

(1)GCD實現的同步異步、串行并行。

——同步sync應用場景:用戶登錄,利用阻塞

——串行異步應用場景:下載等耗時間的任務

/**

*? 因為是異步,所以開通了子線程,但是因為是串行隊列,所以只需要開通1個子線程(2),它們在子線程中順序執行。最常用。

-(void)gcdDemo1{

dispatch_queue_t q1=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_SERIAL);

for (int i=0; i<10; i++) {

dispatch_async(q1, ^{

NSLog(@"%@",[NSThread currentThread]);

});

}

}

*? 因為是異步,所以開通了子線程,且因為是并行隊列,所以開通了好多個子線程,具體幾個,無人知曉,看運氣。線程數量無法控制,且浪費。

-(void)gcdDemo2{

dispatch_queue_t q2=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_CONCURRENT);

for (int i=0; i<10; i++) {

dispatch_async(q2, ^{

NSLog(@"%@",[NSThread currentThread]);

});

}

}

*? 因為是同步,所以無論是并行隊列還是串行隊列,都是在主線程中執行

-(void)gcdDemo3{

dispatch_queue_t q1=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_SERIAL);

for (int i=0; i<10; i++) {

dispatch_sync(q1, ^{

NSLog(@"%@",[NSThread currentThread]);

});

}

}

*? 全局隊列和并行隊列類似(全局隊列不需要創建直接get即可,而導致其沒有名字,不利于后續調試)

-(void)gcdDemo5{

dispatch_queue_t q=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

for (int i=0; i<10; i++) {

dispatch_sync(q, ^{

NSLog(@"%@",[NSThread currentThread]);

});

}

for (int i=0; i<10; i++) {

dispatch_async(q, ^{

NSLog(@"%@",[NSThread currentThread]);

});

}

}

*? 因為是主線程,所以異步任務也會在主線程上運行(1)。而如果是同步任務,則阻塞了,因為主線程一直會在運行,所以后米的任務永遠不會被執行。

*? 主要用處,是更新UI,更新UI一律在主線程上實現

-(void)gcdDemo6{

dispatch_queue_t q=dispatch_get_main_queue();

for (int i=0; i<10; i++) {

dispatch_sync(q, ^{

NSLog(@"%@",[NSThread currentThread]);

});

}

// for (int i=0; i<10; i++) {

// dispatch_async(q, ^{

// NSLog(@"%@",[NSThread currentThread]);

// });

// }

}

(2)NSOperation和NSOperationQueue實現的線程管理

/*

*? 1、只要是自己創建的隊列,添加進來的操作(此處是block操作),都在子線程上(2)

*? 2、只要是在主隊列中,添加進來的操作,都在主線程上(1)

*? 兩個隊列不能同時搶一個任務操作

*/

-(void)opDemo1{

NSOperationQueue *queue=[[NSOperationQueue alloc]init];

NSBlockOperation *b=[NSBlockOperation blockOperationWithBlock:^{

NSLog(@"%@",[NSThread currentThread]);

}];

[queue addOperation:b];

[[NSOperationQueue mainQueue]addOperation:b];

}

/**

*? 同上

*/

-(void)opDemo2{

NSInvocationOperation *i=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(helloWorld) object:nil];

NSOperationQueue *queue=[[NSOperationQueue alloc]init];

[queue addOperation:i];

[[NSOperationQueue mainQueue]addOperation:i];

}

-(void)helloWorld{

NSLog(@"hello,world!");

}

/**

*? 依賴關系:(1)可以保證執行順序,也使得開的子線程不會太多;(2)可以跨隊列,而串行是不可以跨隊列的,如最后更新UI則變成在主隊列中。

*? 這是NSOperation(NSBlockOperation和NSInvocationOperation)和NSOperationQueue的優勢

*/

-(void)opDemo3{

NSBlockOperation *op1=[NSBlockOperation blockOperationWithBlock:^{

NSLog(@"下載圖片 %@",[NSThread currentThread]);

}];

NSBlockOperation *op2=[NSBlockOperation blockOperationWithBlock:^{

NSLog(@"修飾圖片 %@",[NSThread currentThread]);

}];

NSBlockOperation *op3=[NSBlockOperation blockOperationWithBlock:^{

NSLog(@"保存圖片 %@",[NSThread currentThread]);

}];

NSBlockOperation *op4=[NSBlockOperation blockOperationWithBlock:^{

NSLog(@"更新UI %@",[NSThread currentThread]);

}];

[op4 addDependency:op3];

[op3 addDependency:op2];

[op2 addDependency:op1];

NSOperationQueue *queue=[[NSOperationQueue alloc]init];

//設置同一時刻最大開啟的線程數,這是NSOperationQueue特有的

[queue setMaxConcurrentOperationCount:2];

[queue addOperation:op1];

[queue addOperation:op2];

[queue addOperation:op3];

[[NSOperationQueue mainQueue]addOperation:op4];

}

(3)單例的實現(手寫單例要求)dispatch_once運用,即重寫類的allocWithZone方法

@implementation WPObject

+(instancetype)allocWithZone:(struct _NSZone *)zone{

static WPObject *insta;

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

insta=[super allocWithZone:zone];

});

return insta;

}

end

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容