iOS多線程學習筆記(GCD、RunLoop、NSThread),runloopnsthread
//獲得主線程:
[NSThread mainThread];
{number=1, name=main}
//獲得當前線程:
[NSThread currentThread];
//判斷是否主線程:
[NSThread ismainThread];(BOOL)
或者
[[NSThread currentThread] ismainThread];(BOOL)
//pThread使用:(C實現,跨平台,標頭檔#include)
pthread_t thread;
pthread_create(&thread, attributeOfThread, func, funcPara);
//NSThread使用:
NSThread * thread = [[NSThread alloc] initWithTraget:self selector:@seletor(run:) object:runPara];
[thread start];
(建立新線程,run執行完成自動銷毀線程)
或者
[NSThread detachNewThreadSeletor:@seletor(run:) toTarget:self withObject:runPara];
(分離子線程)
或者
[self performSeletorInBackgroud:@seletor(run:) withObject:runPara];
(開啟後台線程)
阻塞線程:
[NSThread sleepForTimeInterval:(float)];
[NSThread sleepUntilDate:[NSDate dateWithIntervalSinceNow:3.0]];
推出線程:(銷毀線程否?)
[NSThread exit];
//原子屬性和非原子屬性:
atomic:會對setter方法加鎖;
nonatomic:不會為setter加鎖;
//線程間通訊:
-(void)performSelectorOnMainThread:(SEL)aSeletor withObject:(id)arg waitUntilDone:(BOOL)wait;
-(void)performSeletor:(SEL)aSeletor onThread:(NSThread*)the withObject:(id)arg waitUntilDone:(BOOL)wait;
//GCD基本使用:(所有函數都以dispatch_開頭,並且使用C語言的形式)
//建立隊列:
dispatch_queue_t queue = dispatch_queue_create(char * label , 宏);
其中宏的值有(即隊列的類型):
DISPATCH_QUEUE_CONCURRENT (並發)
DISPATCH_QUEUE_SERIAL (串列)
//封裝非同步任務block到並發queue隊列中:
dispatch_async(queue , block); (並發隊列)
會開啟新線程,並且非同步執行
//封裝非同步任務block到串列queue隊列中:
dispatch_sync(queue , block); (串列隊列)
也會開啟線程,但只開啟一個線程,串列執行
//封裝同步任務block到並發queue隊列中:
//封裝同步任務block到串列queue隊列中:
dispatch_async(queue , block); (並發隊列)
dispatch_sync(queue , block); (串列隊列)
都不會開啟線程,在主線程中串列執行
//另外,通過調用函數(不是block)封裝任務:
dispatch_async(queue , context, Cfunc);
//全域並發隊列:(獲得已經有的隊列)
dispatch_get_global_queue(優先順序,給未來用預設為0);
其中優先順序有:DISPATCH_QUEUE_PRIORITY_BACKGROUND
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_HIGH
(優先順序由低到高的順序)
//主隊列:凡是在主隊列中的任務,都會放到主線程中執行!
//建立:
dispatch_queue_t queue = dispatch_get_main_queue();
??注意:千萬不要在主線程中把同步函數添加到主隊列中,會發生死結!
??總結:
(1)並發隊列中只能放非同步任務;而串列隊列可以放非同步或同步任務。
(2)同步函數會阻塞當前線程,非同步函數不會阻塞當前線程
(3)如果在主線程中,同步函數因為阻塞了主線程,這樣就不能去建立新線程,但又有新的隊列要去執行,因此就由主線程來串列執行,所以這個時候如果把這個任務加到主隊列中,會產生死結;如果不在主線程中,同步函數只會阻塞當前線程,而因為主線程還在空閑,所以可以調度主線程來執行這些任務
//GCD線程通訊:
建立線程後想回到主線程時,通過嵌套把想要在主線程中執行的代碼放到主隊列中即可!
//順延強制操作以及GCD延遲的優勢:
1.[self performSeletor:@seletor(task) withObject:nil afterDelay:seconds];
2.[NSTimer scheduledTimerWithTimeInterval:seconds target:self selector:@selector(task) userInfo:nil repeats:是否重複];
3.dispatch_after(dispatch_time{相關時間資訊},要放入的隊列,^{要執行的代碼});
GCD優勢時可以決定延遲過後在哪個線程執行block裡的代碼
//GCD實現一次性代碼:
這種一次性指的是這段代碼在整個程式運行期間只會執行一次;而懶載入是指對於某一對象而言,只會載入一次
//iOS RunLoop:
//iOS中有2套架構:NSRunLoop(OC,底層是CFRunLoopRef)和CFRunLoopRef(C)
//CFRunLoop的運行模式叫CFRunLoopModeRef,mode包含source,timer和observer
mode的類型有:(前兩種較常用)
1)kCFRunLoopDefaultMode:預設mode,主線程預設在這個模式下運行
2)UITrackingRunLoopMode:介面跟蹤mode,觸摸滑動時切換到這種模式下
3)UIInitializationRunLoopMode:App啟動時的mode,啟動完成就不再使用
4)GSEventReceiveRunLoopMode:接受系統事件的內部mode,通常用不到
5)kCFRunLoopCommonMode:佔位mode(使事件不受mode切換影響!)