ios的多線程,同步異步操做,都是咱們平常的開發中常常會遇到的問題,本文把常見的ios線程,同步異步的操做進行了整理。
我博客中大部分示例代碼都上傳到了github,地址是:https://github.com/coolnameismy/demo,點擊跳轉代碼下載地址java
本文代碼存放目錄是 ThreadAndAsynchronizationios
若是你們支持,請follow個人github帳號,並fork個人項目,有其餘問題能夠在github上給我留言或者給我發郵件,coolnameismy@hotmail.com,blog的RSS訂閱地址:http://liuyanwei.jumppo.com/pages/rss.xmlgit
線程和進程:網上有一大堆很專業的說法,大多數說的都比較複雜,越複雜的解釋其實說的越準確和嚴謹,可是經常會把人弄糊塗。這裏我也不去解釋了,大多數場景你能夠理解爲,一個應用程序就是一個進程,而一個進程能夠分爲多個線程github
多線程:大多數框架都支持一個進程啓多個線程,好比 c#、java、obejctive-c,可是並非全部的框架都支持,好比flex的框架就不支持多線程。 多線程必需要有多核的cpu支持才行,對應單核cpu,不管你起多少個線程,都是在同一個cpu上跑程序,速度並不會有任何變化。對於多核cpu,多個線程會在多個cpu中同時運行,從而加快程序的執行速度。c#
多線程適用場景 最多見的是網絡下載,在網絡下載的適合,你總不能讓程序一直無響應吧,因此你啓動另外一個線程去下載,留着主線程去相應用戶的ui事件。多線程適合一些高io,低cpu的操做。安全
同步就是順序往下執行。舉例:燒完水後泡茶網絡
異步就是幾件事情同時在執行。燒水的時候拿出茶具,洗茶具,而後泡茶。其中燒水和拿茶具,洗茶具是同時進行的。多線程
並行和串行 並行就是幾我的同時作一件事,串行就是一我的同時作幾件事。框架
同步是咱們通常程序順序執行,異步是大多數時候是多線程,可是卻不必定。好比方法回叫和定時執行的方法也是異步操做,單不必定全是多線程。異步
1 performSelector
支持多線程和異步操做,使用簡單,可是沒有沒有線程的一些控制和調度的操做
2 NSThread
支持多線程和異步操做,使用簡單,比performSelector稍微複雜一些,performSelector背後使用的就是NSThread,可是沒有沒有線程的一些控制和調度的操做
3 NSTimer
不支持多線程操做,可是能夠執行異步操做,異步操做很方便,最經常使用的就是定時執行和延遲執行某一方法
4 GCD
支持多線程,同步異步操做,線程控制,線程隊列,線程信號等等,IOS和OS中最強大的線程管理都是是它了。 要說缺點的話,就是代碼比較複雜,前面能實現的就用前面的把,若是實現不了,那找它準沒錯。
代碼註釋寫的很全,你們直接看註釋都能懂,能夠在github上把代碼下載下來跑跑看。
//ios多線程,同步異步的使用,你們能夠切換類,去掉註釋跑跑看 - (void)viewDidLoad { [super viewDidLoad]; //使用performSelector的多線程和異步 //[self performSelectorFunction]; //使用NSThread的多線程 //[self NSThreadFunction]; //使用NSTimer的反面教材 //[self NSTimerFunction]; //使用GCD的多線程 //[self GCDFunction]; } //耗時2秒的方法 -(void)function1{ [NSThread sleepForTimeInterval:2]; NSLog(@"function1 done"); }
/* *使用performSelector 的多線程 *優勢:簡單 *缺點:沒有串行併線隊列,不能實現高級線程調度 */ -(void)performSelectorFunction{ NSLog(@"performSelectorFunction start"); //同步 //方式執行,直接執行function1 //[self performSelector:@selector(function1)]; //異步,線程阻塞 //延遲兩秒執行function1,在function1執行期間,主線程是阻塞的,表現就是界面無響應。 //[self performSelector:@selector(function1) withObject:nil afterDelay:2]; //線程阻塞 最後一個參決定是同步仍是異步 // 主線程上執行,主線程阻塞,waitUntilDone:YES:等待執行完成順序執行,waitUntilDone:NO 先執行後面語句 //[self performSelectorOnMainThread:@selector(function1) withObject:nil waitUntilDone:NO]; //異步,非阻塞 //子線程上執行 [self performSelectorInBackground:@selector(function1) withObject:nil]; NSLog(@"performSelectorFunction end"); }
/* *使用NSThread 的多線程 *優勢:簡單 *缺點:沒有串行併線隊列,不能實現高級線程調度,和performSelector是同樣的。 */ -(void)NSThreadFunction{ NSLog(@"NSThreadFunction start"); //同步 阻塞 //線程暫停 2秒 //[NSThread sleepForTimeInterval:2]; //異步 非阻塞 //顯示建立的方式執行 //NSThread *myThread = [[NSThread alloc]initWithTarget:self selector:@selector(function1) object:nil]; //[myThread start]; //異步 非阻塞 //靜態方法執行線程 //[NSThread detachNewThreadSelector:@selector(function1) toTarget:self withObject:nil]; NSLog(@"NSThreadFunction end"); }
/* *使反面教材,他不是多線程,但能夠執行異步操做。最經常使用的就是定時執行一個任務,重複或非重複。 */ -(void)NSTimerFunction{ NSLog(@"NSTimerFunction start"); //定時執行任務,能夠重複和不重複 //NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(function1) userInfo:nil repeats:NO]; //暫時中止定時器 //[timer setFireDate:[NSDate distantFuture]]; //從新開啓定時器 //[timer setFireDate:[NSDate distantPast]]; //永久通知定時器 //[timer invalidate]; //timer = nil; NSLog(@"NSTimerFunction end"); }
GCD的方法不少,用法也不少,這裏只列舉一些經常使用的方法。經常使用的方法包括:
同步、非阻塞執行
異步非阻塞執行
一次性執行
延遲執行
線程隊列串行執行
線程隊列控制(屏障,同步等待,線程暫停和恢復,線程信號量控制等)
/* *使用GCD 的多線程 *優勢:有不少串行併線隊列多線程,block實現線程方法,高級,好用,方法多。 *缺點:在不少不須要高級控制線程的場景能夠不用使用GCD */ -(void)GCDFunction{ NSLog(@"GCDFunction start"); //獲取一個隊列 dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //dispatch_async:異步方式執行方法(最經常使用) // dispatch_async(defaultQueue, ^{ // [self function1]; // }); //dispatch_sync:同步方式使用場景,比較少用,通常與異步方式進行調用 // dispatch_async(defaultQueue, ^{ // NSMutableArray *array = [self GCD_sync_Function]; // dispatch_async(dispatch_get_main_queue(), ^{ // //利用獲取的arry在主線程中更新UI // // }); // }); //dispatch_once:一次性執行,經常用戶單例模式.這種單例模式更安全 // static dispatch_once_t onceToken; // dispatch_once(&onceToken, ^{ // // code to be executed once // NSLog(@"dispatch_once"); // }); //dispatch_after 延遲異步執行 // dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC); // dispatch_after(popTime, defaultQueue, ^{ // NSLog(@"dispatch_after"); // }); //dispatch_group_async 組線程能夠實現線程之間的串聯和並聯操做 // dispatch_group_t group = dispatch_group_create(); // NSDate *now = [NSDate date]; // //作第一件事 2秒 // dispatch_group_async(group, defaultQueue, ^{ // [NSThread sleepForTimeInterval:2]; // NSLog(@"work 1 done"); // }); // //作第二件事 5秒 // dispatch_group_async(group, defaultQueue, ^{ // [NSThread sleepForTimeInterval:5]; // NSLog(@"work 2 done"); // }); // // //兩件事都完成後會進入方法進行通知 // dispatch_group_notify(group, defaultQueue, ^{ // NSLog(@"dispatch_group_notify"); // NSLog(@"%f",[[NSDate date]timeIntervalSinceDate:now]);//總共用時5秒,由於2個線程同時進行 // }); //dispatch_barrier_async :做用是在並行隊列中,等待前面的隊列執行完成後在繼續往下執行 // dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT); // dispatch_async(concurrentQueue, ^{ // [NSThread sleepForTimeInterval:2]; // NSLog(@"work 1 done"); // }); // dispatch_async(concurrentQueue, ^{ // [NSThread sleepForTimeInterval:2]; // NSLog(@"work 2 done"); // }); // //等待前面的線程完成後執行 // dispatch_barrier_async(concurrentQueue, ^{ // NSLog(@"dispatch_barrier_async"); // }); // // dispatch_async(concurrentQueue, ^{ // [NSThread sleepForTimeInterval:3]; // NSLog(@"work 3 done"); // }); //dispatch_semaphore 信號量的使用,串行異步操做 // dispatch_semaphore_create 建立一個semaphore // dispatch_semaphore_signal 發送一個信號 // dispatch_semaphore_wait 等待信號 /*應用場景1:馬路有2股道,3輛車經過 ,每輛車經過須要2秒 *條件分解: 馬路有2股道 <=> dispatch_semaphore_create(2) //建立兩個信號 三樓車經過 <=> dispatch_async(defaultQueue, ^{ } 執行三次 車經過須要2秒 <=> [NSThread sleepForTimeInterval:2];//線程暫停兩秒 */ dispatch_semaphore_t semaphore = dispatch_semaphore_create(2); dispatch_async(defaultQueue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); [NSThread sleepForTimeInterval:2]; NSLog(@"carA pass the road"); dispatch_semaphore_signal(semaphore); }); dispatch_async(defaultQueue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); [NSThread sleepForTimeInterval:2]; NSLog(@"carB pass the road"); dispatch_semaphore_signal(semaphore); }); dispatch_async(defaultQueue, ^{ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); [NSThread sleepForTimeInterval:2]; NSLog(@"carC pass the road"); dispatch_semaphore_signal(semaphore); }); //應用場景2 :原子性保護,保證同時只有一個線程進入操做 // dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); // for(int i=0 ;i< 10000 ;i++){ // dispatch_async(defaultQueue, ^{ // dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // NSLog(@"i:%d",i); // dispatch_semaphore_signal(semaphore); // }); // } NSLog(@"GCDFunction end"); }