ios的線程和同步異步操做

ios的線程和同步異步操做

ios的線程和同步異步操做

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

基礎知識


1.線程和進程 ,多線程

線程和進程:網上有一大堆很專業的說法,大多數說的都比較複雜,越複雜的解釋其實說的越準確和嚴謹,可是經常會把人弄糊塗。這裏我也不去解釋了,大多數場景你能夠理解爲,一個應用程序就是一個進程,而一個進程能夠分爲多個線程github

多線程:大多數框架都支持一個進程啓多個線程,好比 c#、java、obejctive-c,可是並非全部的框架都支持,好比flex的框架就不支持多線程。 多線程必需要有多核的cpu支持才行,對應單核cpu,不管你起多少個線程,都是在同一個cpu上跑程序,速度並不會有任何變化。對於多核cpu,多個線程會在多個cpu中同時運行,從而加快程序的執行速度。c#

多線程適用場景 最多見的是網絡下載,在網絡下載的適合,你總不能讓程序一直無響應吧,因此你啓動另外一個線程去下載,留着主線程去相應用戶的ui事件。多線程適合一些高io,低cpu的操做。安全

2.同步和異步,並行和串行

同步就是順序往下執行。舉例:燒完水後泡茶網絡

異步就是幾件事情同時在執行。燒水的時候拿出茶具,洗茶具,而後泡茶。其中燒水和拿茶具,洗茶具是同時進行的。多線程

並行和串行 並行就是幾我的同時作一件事,串行就是一我的同時作幾件事。框架

3.同步異步操做和多線程的聯繫和區別

同步是咱們通常程序順序執行,異步是大多數時候是多線程,可是卻不必定。好比方法回叫和定時執行的方法也是異步操做,單不必定全是多線程。異步

4.ios中的同步異步方法和多線程技術

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"); }

1. performSelector的使用

/*  *使用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"); }

2. NSThreadFunction的使用

/*  *使用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"); }

3. NSTimerFunction的使用

/*  *使反面教材,他不是多線程,但能夠執行異步操做。最經常使用的就是定時執行一個任務,重複或非重複。  */ -(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"); }

4. GCD的使用

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"); }
相關文章
相關標籤/搜索