iOS多線程技術

來源:互聯網
上載者:User

標籤:

說明:開發技術大同小異,文章寫出來不是為了曬的,只是一個學習記錄過程,有錯誤歡迎指正,喜歡噴人的請滾蛋。

一、實現方案

在iOS中有三種多線程實現技術,它們分別是NSThread、GCD 、NSOperation。

  NSThread:基於OC編寫,更加物件導向,可直接操作線程對象,需要程式員手動管理線程生命週期,開發中偶爾使用。

  GCD:基於c語言編寫,旨在替代NSThread線程技術,能充分利用裝置的多核,系統自動管理線程生命週期,開發中經常使用。

  NSOperation:底層基於GCD封裝的一套OC實現,更加物件導向,系統自動管理線程生命週期,開發中經常使用。

1.NSThread

一個NSthread對象就代表一條線程

相關設定

 

設定線程的名字

 

- (void)setName:(NSString *)name;

 

- (NSString *)name;

 

獲得當前線程

 

[NSThread currentThread];

 

線程調度優先順序:優先順序範圍在0.0~1.0之間,預設是0.5,值越大,優先順序越高,越容易被調度。

 

- (void)setThreadPriority:(double)priority

 

- (double)threadPriority

 

主線程

 

+ (NSThread *)mainThread; // 獲得主線程

 

- (BOOL)isMainThread; // 是否為主線程

 

+ (BOOL)isMainThread; // 是否為主線程

 

1.線程的建立

 1>NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(callback) object:nil];

 [thread start];

2>[NSThread detachNewThreadSelector:@selector(callback:) toTarget:self withObject:nil];

3>[self performSelectorInBackground:@selector(callback:) withObject:nil];

第一種相比較後兩種而言可以更加精準的控制線程相關設定,比如線程名稱,優先順序等。

2.線程的狀態

建立:線程建立出來

就緒:調用線程start方法,載入到線程池等待調度

運行:線程得到cpu調度

阻塞:線程睡眠或等待同步鎖

死亡:線程執行完畢或者強制退出或者程式崩潰

3.線程的同步

當多個線程訪問共用資源時,會有資料安全問題,例如寫出錯,讀取髒資料,解決辦法是加互斥鎖。

//加鎖

 @synchronized(self){

  訪問共用資源代碼

}//解鎖

4.線程的通訊

有時候多個線程之間需要相互連信,互相傳遞資料,比如在子線程下載好圖片資源後需要回到主線程更新UI介面

可以在子線程內部發發非同步請求向主線程傳遞資料。

- (void)threadCommunicate

{

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download) object:nil];

    [thread setThreadPriority:1];

    thread.name = @"線程A";

    [thread start];

}

- (void)download

{

    //1.下載圖片

    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"]];

    UIImage *image = [UIImage imageWithData:data];

    //2.更新圖片(子線程下載的圖片返回給主線程更新UI介面)

    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];

}

2.GCD(Grand Central Dispatch)

GCD會充分利用裝置的多核技術,自動管理線程的生命週期,程式員只需要將任務放在相關隊列中就可以了,不用關心線程的狀態

首先理解兩個概念

隊列:

串列隊列:隊列的任務串列執行

並發隊列:隊列的任務並發執行

請求:

同步:不會開啟新線程

非同步:會開啟新線程,只有放在並發隊列中才會實現多線程技術,放在串列隊列中只會開啟一個線程且任務串列執行。

- (void)viewDidLoad{    [super viewDidLoad];    //1.串列隊列(隊列裡面的操作串列執行)    self.serialQueue = dispatch_queue_create("串列對列",DISPATCH_QUEUE_SERIAL);    //2.並發隊列(隊列裡面的操作並發執行)    self.concurrentQueue = dispatch_queue_create("並行隊列",DISPATCH_QUEUE_CONCURRENT);    //3.全域隊列(系統內建並發隊列)    self.globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    //4.主隊列(與主線程相關)    self.mainQueue = dispatch_get_main_queue();    NSLog(@"主線程%@",[NSThread currentThread]);    //[self gcdCommunicate];}/** * 同步函數dispatch_sync不會開啟新線程 */- (void)sync{    //在串列隊列中同步執行操作    for(int i = 0;i<10;i++){        dispatch_sync(self.serialQueue, ^{            NSLog(@"同步串列%@--%d",[NSThread currentThread],i);        });    }    //在並發隊列中同步執行操作    for(int i = 0;i<10;i++){        dispatch_sync(self.concurrentQueue, ^{            NSLog(@"同步並發%@",[NSThread currentThread]);        });    }    //在全域隊列中同步執行操作    for(int i = 0;i<10;i++){        dispatch_sync(self.globalQueue, ^{            NSLog(@"同步全域%@",[NSThread currentThread]);        });    }    //在主隊列中同步執行操作#warning 在主線程中執行同步操作會卡住    dispatch_sync(self.mainQueue, ^{        NSLog(@"同步主%@",[NSThread currentThread]);    });}/** * 非同步函數dispatch_async會開啟新線程 */- (void)async{    //在串列隊列中非同步執行操作(開啟一條子線程,操作串列執行)    for(int i = 0;i<10;i++){        dispatch_async(self.serialQueue, ^{            NSLog(@"非同步串列%@---%d",[NSThread currentThread],i);        });    }    //在並發隊列中非同步執行操作(開啟多條子線程,操作並發執行)    for(int i = 0;i<10;i++){        dispatch_async(self.concurrentQueue, ^{            NSLog(@"非同步並發%@---%d",[NSThread currentThread],i);        });    }    //在全域隊列中非同步執行操作(開啟多條子線程,操作並發執行)    for(int i = 0;i<10;i++){        dispatch_async(self.globalQueue, ^{            NSLog(@"非同步全域%@---%d",[NSThread currentThread],i);        });    }    //在主隊列中非同步執行操作(在主線程上執行,操作串列執行)    for(int i = 0;i<10;i++){        dispatch_async(self.globalQueue, ^{            NSLog(@"非同步主%@---%d",[NSThread currentThread],i);        });    }}/** * GCD的線程通訊 */- (void)gcdCommunicate{    dispatch_async(self.globalQueue, ^{        NSLog(@"當前線程%@", [NSThread currentThread]);        // 下載圖片        NSURL *url = [NSURL URLWithString:@"http://news.baidu.com/z/resource/r/image/2014-06-22/2a1009253cf9fc7c97893a4f0fe3a7b1.jpg"];        NSData *data = [NSData dataWithContentsOfURL:url];         UIImage *image = [UIImage imageWithData:data];                // 回到主線程顯示圖片        dispatch_async(self.mainQueue, ^{            NSLog(@"當前線程%@", [NSThread currentThread]);            self.imageView.image = image;        });    });}

3.NSOperation

NSOperation底層基於GCD,使用OC編寫,更加物件導向,是蘋果官方比較推薦的技術

配合使用NSOperation和NSOperationQueue也能實現多線程編程

1>使用步驟

 首先建立NSOperation對象,將操作封裝到裡面

然後將NSOperation對象添加到NSOperationQueue中

系統會自動將NSOperation中封裝的操作放到一條新線程中執行

2>子類

NSOperation是個抽象類別,並不具備封裝操作的能力,必須使用它的子類

使用NSOperation子類的方式有3種

NSInvocationOperation

NSBlockOperation

自訂子類繼承NSOperation,實現內部相應的方法

/** * NSInvocationOperation的使用 */- (void)invocationOperation{    // 1.建立操作對象, 封裝要執行的操作    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(callback) object:nil];    // 2.啟動操作(預設情況下,如果操作沒有放到隊列queue中,都是同步執行)    [operation start];}- (void)callback{    NSLog(@"當前線程%@",[NSThread currentThread]);}/** * NSBlockOperation的使用 */- (void)blockOperation{    // 1.建立操作對象, 封裝要執行的操作    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"當前線程%@--操作1",[NSThread currentThread]);    }];    [operation addExecutionBlock:^{        NSLog(@"當前線程%@--操作2",[NSThread currentThread]);    }];    [operation addExecutionBlock:^{        NSLog(@"當前線程%@--操作3",[NSThread currentThread]);    }];    //監聽操作    operation.completionBlock = ^(){        NSLog(@"當前線程%@--操作完畢", [NSThread currentThread]);    };    // 2.啟動操作(如果只有一個操作不會開啟線程,如果有多個操作,就會開啟新線程)    [operation start];}/** * NSOperationQueue的使用 */- (void)OperationQueue{    //1.建立操作隊列    NSOperationQueue *queue = [[NSOperationQueue alloc] init];    //設定隊列的最大並發數    queue.maxConcurrentOperationCount = 3;    //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(invocation) object:nil];        //設定依賴    //[operation2 addDependency:operation1];    //[operation3 addDependency:operation2];            //3.操作放在隊列中    [queue addOperation:operation1];    [queue addOperation:operation2];    [queue addOperation:operation3];}- (void)invocation{    NSLog(@"當前線程%@-操作3",[NSThread currentThread]);}

//寫的有點晚了,本來想寫細點,不過感覺這些代碼和思想都很簡單,方便以後自己重溫就行了,所以寫的糙了點,海涵。

 

iOS多線程技術

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.