iOS多线程总结
2019獨角獸企業重金招聘Python工程師標準>>>
一 多線程之間的關系
2、
二?NSThread
一旦線程停止死亡了,就不能再啟動。所以線程NSThread不能為全局變量
1>.創建和啟動
1.第一種方法:直接創建,手動啟動NSThread?*thread?=?[[NSThread?alloc]?initWithTarget:self?selector:@selector(download:)?object:@"www.baidu.com"];[thread?start];2.第二種方法:創建后立即啟動????[NSThread?detachNewThreadSelector:@selector(download)?toTarget:self?withObject:@"www.baidu.com"];3.第三種方法:隱式創建//主線程[self?performSelector:@selector(download:)?withObject:@"www.baidu.com"];//子線程[self?performSelectorInBackground:@selector(download:)?withObject:@"www.baidu.com"];object是selector方法傳遞的參數 -(void)download:(NSString?*)url {NSLog(@"download--?%@??%@",url,[NSThread?currentThread]); }2>.睡眠的用法
延遲執行不要勇sleep,壞處:卡住主線程 1.第一種[NSThread?sleepForTimeInterval:5.0]; 2.第二種????NSDate?*date?=?[NSDate?dateWithTimeIntervalSinceNow:3.0];[NSThread?sleepUntilDate:date];3>.強制停止進程
+(void)exit4>.其他用法
+(NSThread?*)mainThread; +(NSThread?*)currentThread -(BOOL)isMainThread; +(BOOL)isMainThread;5>.線程間通信
在1個進程中,線程往往不是孤立存在的,多個線程之間需要經常進行通信。體現在兩個方面:一,1個線程的數據傳遞給另一個線程。二,在1個線程中執行完特定任務后,轉到另一個線程繼續執行任務
三 GCD
1>線程:同步與異步
同步:只能在當前線程中執行任務,不具備開啟新線程的能力
異步:可以在新的線程中執行任務,具備開啟新線程的能力
2>任務:并發與串行
并發:可以讓多個任務并發(同時)執行,自動開啟多線程。只有在異步下才有效
串行:讓任務一個接一個地執行
-(void)asyncGlobalQueue {//獲得全局的并發隊列dispatch_queue_t?queue?=?dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,?0);?//第一個參數是優先級//異步并行。自動創建多條線程dispatch_async(queue,?^{NSLog(@"將任務放到全局隊列中執行?%@",??[NSThread?currentThread]);dispatch_async(queue,?^{NSLog(@"異步并行1?%@",??[NSThread?currentThread]);});dispatch_async(queue,?^{NSLog(@"異步并行2?%@",??[NSThread?currentThread]);});dispatch_async(queue,?^{NSLog(@"異步并行3?%@",??[NSThread?currentThread]);});dispatch_async(queue,?^{NSLog(@"異步并行4?%@",??[NSThread?currentThread]);});dispatch_async(queue,?^{NSLog(@"異步并行5?%@",??[NSThread?currentThread]);});}); }-(void)asyncSerialQueue {//異步串行,自動會創建線程,但只開1條dispatch_queue_t?queue?=?dispatch_queue_create("cn.wx",?NULL);dispatch_async(queue,?^{NSLog(@"異步串行1?%@",??[NSThread?currentThread]);});dispatch_async(queue,?^{NSLog(@"異步串行2?%@",??[NSThread?currentThread]);});dispatch_async(queue,?^{NSLog(@"異步串行3?%@",??[NSThread?currentThread]);});dispatch_async(queue,?^{NSLog(@"異步串行4?%@",??[NSThread?currentThread]);});dispatch_async(queue,?^{NSLog(@"異步串行5?%@",??[NSThread?currentThread]);}); }-(void)syncGlobalQueue {dispatch_queue_t?queue?=?dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,?0);//同步并行。不會創建線程,使用主線程dispatch_sync(queue,?^{NSLog(@"同步并行1?%@",??[NSThread?currentThread]);NSLog(@"同步并行2?%@",??[NSThread?currentThread]);NSLog(@"同步并行3?%@",??[NSThread?currentThread]);NSLog(@"同步并行4?%@",??[NSThread?currentThread]);NSLog(@"同步并行5?%@",??[NSThread?currentThread]);}); }-(void)syncSerialQueue {dispatch_queue_t?queue?=?dispatch_queue_create("cn.wx",?NULL);//同步串行。不會創建線程,使用主線程dispatch_sync(queue,?^{NSLog(@"同步并行1?%@",??[NSThread?currentThread]);NSLog(@"同步并行2?%@",??[NSThread?currentThread]);NSLog(@"同步并行3?%@",??[NSThread?currentThread]);NSLog(@"同步并行4?%@",??[NSThread?currentThread]);NSLog(@"同步并行5?%@",??[NSThread?currentThread]);}); }3>.主隊列
-(void)mainQueue {dispatch_queue_t?queue?=?dispatch_get_main_queue();dispatch_async(queue,?^{NSLog(@"雖然是異步,但是是在主線程執行,所以不會開線程");}); //????dispatch_sync(queue,?^{ //????????NSLog(@"不能在串行上使用主隊列,否則會阻塞"); //????});}4>.線程間通信
????dispatch_queue_t?queue?=?dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,?0);dispatch_async(queue,?^{NSLog(@"子線程進行操作");dispatch_async(dispatch_get_main_queue(),?^{NSLog(@"回主線程加載圖片");});});5>.延時執行
不要使用sleep,會卡住主線程
第一種: [self?performSelector:@selector(down)?withObject:@"abv"?afterDelay:3]; 第二種:dispatch_queue_t?queue?=?dispatch_get_main_queue();dispatch_after(dispatch_time(DISPATCH_TIME_NOW,?(int64_t)(3?*?NSEC_PER_SEC)),?queue,?^{NSLog(@"xx");//回到主線程});dispatch_queue_t?queue?=?dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,?0);dispatch_after(dispatch_time(DISPATCH_TIME_NOW,?(int64_t)(3?*?NSEC_PER_SEC)),?queue,?^{NSLog(@"xx");//回到子線程});6>.只執行一次
????static?dispatch_once_t?onceToken;dispatch_once(&onceToken,?^{NSLog(@"xx");})四 NSOperation
1>.簡述
先將需要執行的操作封裝到一個NSOperation對象,一個對象就相當于GCD的一個block
然后將NSOperation對象添加到NSOperationQueue中
系統會自動將NSOperationQueue中的NSOperation取出來
將取出的NSOperation封裝的操作放到一條線程中執行
2>.NSOperation的使用
NSOperation是個抽象類,不具備封裝的能力,必須使用它的子類
1>NSInvocationOperation
????NSInvocationOperation?*operation?=?[[NSInvocationOperation?alloc]?initWithTarget:self?selector:@selector(download)?object:nil];/*[operation?start];?如果直接start,那么將會在當前線程(主線程)同步執行*///添加操作到隊列中[queue?addOperation:operation];2>NSBlockOperation
第一種情況:同步NSBlockOperation?*operation?=?[NSBlockOperation?blockOperationWithBlock:^{NSLog(@"下載一?%@",[NSThread?currentThread]);}];[operation?start];?//?如果直接start,那么將會在當前線程(主線程)同步執行第二種情況:異步NSBlockOperation?*operation?=?[[NSBlockOperation?alloc]?init];//operation操作添加多個操作[operation?addExecutionBlock:^{NSLog(@"下載一?%@",[NSThread?currentThread]);}];[operation?addExecutionBlock:^{NSLog(@"下載二?%@",[NSThread?currentThread]);}];[operation?addExecutionBlock:^{NSLog(@"下載三?%@",[NSThread?currentThread]);}];[operation?start];ps:NSBlockOperation還可以直接創建使用對象NSBlockOperation?*operation?=?[NSBlockOperation?blockOperationWithBlock:^{NSLog(@"下載一?%@",[NSThread?currentThread]);}];3>自定義子類繼承NSOperation
3.NSOperationQueue的使用
1>.基本使用
????//1.創建一個隊列(非主隊列)NSOperationQueue?*queue?=?[[NSOperationQueue?alloc]?init];//設置最大并發數queue.maxConcurrentOperationCount?=?2;//2.創建操作NSBlockOperation?*operation1?=?[NSBlockOperation?blockOperationWithBlock:^{NSLog(@"下載圖片1?--?%@",[NSThread?currentThread]);}];NSBlockOperation?*operation2?=?[NSBlockOperation?blockOperationWithBlock:^{NSLog(@"下載圖片2?--?%@",[NSThread?currentThread]);}];NSInvocationOperation?*operation3?=?[[NSInvocationOperation?alloc]?initWithTarget:self?selector:@selector(down)?object:nil];//操作完后馬上執行另一個操作[operation1?setCompletionBlock:^{NSLog(@"下載圖片222");}];//操作依賴,注意不能相互依賴[operation2?addDependency:operation1];[operation3?addDependency:operation2];//3.添加操作到隊列中(自動異步執行任務,并發)[queue?addOperation:operation1];[queue?addOperation:operation2];[queue?addOperation:operation3];2>其他用法
????[queue?cancelAllOperations];?//取消隊列的所有操作。也可以直接調用NSOperation的cancel[queue?setSuspended:YES];?//暫停和恢復隊列。yes為暫停常用場景: -(void)didReceiveMemoryWarning {[super?didReceiveMemoryWarning];[queue?cancelAllOperations]; }-(void)scrollViewWillBeginDecelerating:(UIScrollView?*)scrollView {[queue?setSuspended:YES]; }-(void)scrollViewDidEndDragging:(UIScrollView?*)scrollView?willDecelerate:(BOOL)decelerate {[queue?setSuspended:NO]; }3>.線程安全
????NSOperationQueue?*queue?=?[[NSOperationQueue?alloc]?init];[queue?addOperationWithBlock:^{//1.異步下載圖片NSURL?*url?=?[NSURL?URLWithString:@"www.baidu.com"];NSData?*data?=?[NSData?dataWithContentsOfURL:url];UIImage?*image?=?[UIImage?imageWithData:data];//2.回到主線程設置圖片[[NSOperationQueue?mainQueue]?addOperationWithBlock:^{self.imageView.image?=?image;}];}];五 互斥鎖
????self.obj?=?[[NSObject?alloc]?init];//鎖任意對象,并且需要是唯一一把,所以需要建立個全局變量對象@synchronized(self.obj)?{}2.atomic:線程安全,需要消耗大量的資源。不建議需要
六 線程注意點
1.不要同時開太多線材(1~3條線材即可,不要超過5條)
2.線程概念
1>主線程:UI線程,顯示、刷新UI界面,處理UI控件的事件
2>子線程:后臺線程,異步線程
3.不要把耗時的操作放在主線程,要放在子線程中執行
轉載于:https://my.oschina.net/u/2346786/blog/537424
總結
- 上一篇: CSS - 层叠特性
- 下一篇: lua中元素的下标是从1开始的