2018年4月30日 星期一

NSThread, GCD

NSThread

有三種方式可以開Thread
  1. NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test:) object:nil];
  2. [NSThread detachNewThreadSelector:@selector(test:) toTarget:self withObject:@"分离子线程"];
    [self performSelectorInBackground:@selector(test:) withObject:@"后台线程"];

第一種方式可以取得該線程的instance,也可以設定Thread Priority,但要手動啟動線程
第二三種方式直接開啟線程,但無法取得instance
performSelector是比較早期的API,跟NSThreadㄧ樣呼叫一次就開一個線程 
目前Object-C大多使用GCD或是NSOperationQueue,這兩個API會自行管理線程數量



GCD

分作兩種模式
  1. dispatch_async :非同步
  2. dispatch_sync:同步
同步模式下會先等待Block裡面的動作執行完,才繼續往下跑
個人感覺有點類似C#的async Task 搭配 await語法,會把工作丟給別的Thread去做,但會等工作做完才繼續動作

實際上使用dispatch_sync後,發現動作並沒有在其他Thread執行,而是使用main thread,爬文之後發現有人在討論這個問題



也就是說因為main queue是serial queue,呼叫dispatch_sync必定導致線程block住,無所謂執行block內工作的線程,所以程式會直接使用main queue執行,節省開線程的資源

如果今天是在背景呼叫dispatch_sync把工作丟給main queue,就會有線程切換的動作

簡單來說 dispatch_sync 不會開新線程,但在特定情況下,會有線程切換

另外使用dispatch_async也不一定呼叫幾次就開啟多少線程,程式會自行控制
推測應該跟C#一樣使用thread pool的概念
有文章說線程上限66個,serial 與 concurrent共用這數量


使用GCD要小心Block的問題,千萬不要在同步模式(dispatch_sync) 下丟一個Block給自己的線程,自己等自己會卡住

dispatch_queue 可以分為兩種,serial queue與concurrent queue
main_queue:serial queue
global_queue:於concurrent queue
用dispatch_queue_t可以自行宣告,自行決定類型

GCD使用方法



當函式使用非同步模式,又必須回傳其運作結果時,需要使用dispatch_semaphore_t
類似於async await,之後會詳細描述

http://www.iosxxx.com/blog/2016-06-02-GCD那些事.html

沒有留言:

張貼留言