iOS-GCD多線程編程詳解6編程
這篇主要講的函數是dispatch_semaphore的dispatch_semaphore_create,dispatch_semaphore_wait,dispatch_semaphore_signal函數的使用。dispatch_semaphore_t 的做用是異步多線程的信號傳遞來達到多線程的依賴執行,說白了就是經過信號來在多線程中傳遞來達到線程是否繼續執行的條件,線程經過信號來決定是否繼續執行,下面來看具體的使用及說明。多線程
一.dispatch_semaphore_t函數說明異步
1.dispatch_semaphore_t dispatch_semaphore_create(long value)-》該函數的做用是建立一個dispatch_semaphore_t的信號變量,傳人的參數爲long int 類型的value, 當value的值傳人0主要用於兩個線程對一個特定的事件要保持一致性。傳人大於0 的數主要用於管理有限個資源池,池中資源的數量等於傳人的value。async
2.long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);該函數的做用是爲了在該線程中等待信號,當timeout的時間到了,就會執行該線程中的指令。傳人的dsema爲dispatch_semaphore_t的變量,timeout爲等待的時間,若是timeout時間到了就會執行該線程下面的指令。返回值爲long類型,若是返回值爲0表示執行完成,若是爲非0表示超時。讀者能夠經過返回值來判斷來執行不一樣狀況的代碼。函數
3.long dispatch_semaphore_signal(dispatch_semaphore_t dsema);該函數爲增長信號量,返回值類型爲long類型,當爲0時表示線程在執行block,非0 表示block任務等待狀態。傳人的參數爲信號量。spa
二.函數各類組合及結果分析線程
第一種不使用dispatch_semaphore_t的異步調用:設計
dispatch_queue_t queue = dispatch_queue_create("My_QUEUE", NULL); dispatch_async(queue, ^{ NSLog(@"異步線程%@",[NSThread currentThread]); }); NSLog(@"主線程%@",[NSThread currentThread]);
1.3d
2015-01-10 17:58:31.219 GCDTest[1699:93299] 主線程<NSThread: 0x7fe190e27910>{number = 1, name = main}code
2015-01-10 17:58:31.219 GCDTest[1699:93346] 異步線程<NSThread: 0x7fe190d06d60>{number = 2, name = (null)}
2.
2015-01-10 18:00:07.940 GCDTes[1709:94085] 主線程<NSThread: 0x7f9620d27cf0>{number = 1, name = main}
2015-01-10 18:00:07.940 GCDTest[1709:94138] 異步線程<NSThread: 0x7f9620e18100>{number = 2, name = (null)}
結果分析:主線程的優先級別比異步線程的優先級別高,因此它的運行時間片比異步線程多,因此主線程先輸出。
第二種使用狀況,加入dispatch_semaphore_t 等待時間爲10秒
dispatch_queue_t queue = dispatch_queue_create("My_QUEUE", NULL);//建立一個隊列 dispatch_semaphore_t sema = dispatch_semaphore_create(0);//建立一個信號量 dispatch_async(queue, ^{ //異步執行一個線程 NSLog(@"異步線程%@",[NSThread currentThread]); long int threadState = dispatch_semaphore_signal(sema); //得到該block是否被執行的狀態 if (threadState) { NSLog(@"該線程unwoken%@",[NSThread currentThread]); }else{ NSLog(@"該線程woken%@",[NSThread currentThread]); } dispatch_semaphore_signal(sema); }); long int state = dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 10000000000)); if(state){ //判斷時超時了仍是正常的執行完成超時時間爲10秒 NSLog(@"超時"); }else{ NSLog(@"執行成功"); } NSLog(@"主線程%@",[NSThread currentThread]);
1.
2015-01-10 18:18:01.847 GCDTest[1969:102210] 異步線程<NSThread: 0x7fcfe9d2e380>{number = 2, name = (null)}
2015-01-10 18:18:01.848 GCDTest[1969:102210] 該線程unwoken<NSThread: 0x7fcfe9d2e380>{number = 2, name = (null)}
2015-01-10 18:18:01.848 GCDTest[1969:102182] 執行成功
2015-01-10 18:18:01.848 GCDTest[1969:102182] 主線程<NSThread: 0x7fcfe9d25250>{number = 1, name = main}
2.
2015-01-10 18:27:34.153 GCDTest[1999:104402] 異步線程<NSThread: 0x7ffd48e32dd0>{number = 2, name = (null)}
2015-01-10 18:27:34.153 GCDTest[1999:104370] 執行成功
2015-01-10 18:27:34.153 GCDTest[1999:104402] 該線程unwoken<NSThread: 0x7ffd48e32dd0>{number = 2, name = (null)}
2015-01-10 18:27:34.154 GCDTest[1999:104370] 主線程<NSThread: 0x7ffd48f14ab0>{number = 1, name = main}
函數,因而就等待10秒鐘,這時異步線程得到了運行時間片,由於主線程在等待信號量是線程時掛起狀態,因此輸出unwoken,由於主線程等待了10秒鐘,在這十秒鐘內異步線程執行完成了因此輸出「執行完成」,以後在執行主線程下面的內容。
第三種使用狀況,加入dispatch_semaphore_t 等待時間爲十億分之一秒
dispatch_queue_t queue = dispatch_queue_create("My_QUEUE", NULL);//建立一個隊列 dispatch_semaphore_t sema = dispatch_semaphore_create(0);//建立一個信號量 dispatch_async(queue, ^{ //異步執行一個線程 NSLog(@"異步線程%@",[NSThread currentThread]); long int threadState = dispatch_semaphore_signal(sema); //得到該block是否被執行的狀態 if (threadState) { NSLog(@"該線程unwoken%@",[NSThread currentThread]); }else{ NSLog(@"該線程woken%@",[NSThread currentThread]); } dispatch_semaphore_signal(sema); }); long int state = dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 1)); if(state){ //判斷時超時了仍是正常的執行完成超時時間爲10 億分之 1秒 NSLog(@"超時"); }else{ NSLog(@"執行成功"); } NSLog(@"主線程%@",[NSThread currentThread]);
1.
2015-01-10 18:32:31.503 GCDTest[2123:107351] 異步線程<NSThread: 0x7fc12a70f790>{number = 2, name = (null)}
2015-01-10 18:32:31.503 GCDTest[2123:107326] 超時
2015-01-10 18:32:31.504 GCDTest[2123:107351] 該線程woken<NSThread: 0x7fc12a70f790>{number = 2, name = (null)}
2015-01-10 18:32:31.504 GCDTest[2123:107326] 主線程<NSThread: 0x7fc12a416a70>{number = 1, name = main}
2.
2015-01-10 18:32:49.667 GCDTest[2129:107629] 超時
2015-01-10 18:32:49.667 GCDTest[2129:107657] 異步線程<NSThread: 0x7fa139c7aa80>{number = 2, name = (null)}
2015-01-10 18:32:49.667 GCDTest[2129:107657] 該線程woken<NSThread: 0x7fa139c7aa80>{number = 2, name = (null)}
2015-01-10 18:32:49.667 GCDTest[2129:107629] 主線程<NSThread: 0x7fa139c29310>{number = 1, name = main}
3.
2015-01-10 18:33:12.352 GCDTest[2134:107906] 異步線程<NSThread: 0x7ff75a63d8b0>{number = 2, name = (null)}
2015-01-10 18:33:12.353 GCDTest[2134:107906] 該線程woken<NSThread: 0x7ff75a63d8b0>{number = 2, name = (null)}
2015-01-10 18:33:12.352 GCDTest[2134:107878] 超時
2015-01-10 18:33:12.354 GCDTest[2134:107878] 主線程<NSThread: 0x7ff75a413490>{number = 1, name = main}
4.
2015-01-10 18:34:23.583 GCDTest[2141:108330] 超時
2015-01-10 18:34:23.584 GCDTest[2141:108330] 主線程<NSThread: 0x7fdde8426f30>{number = 1, name = main}
2015-01-10 18:34:23.583 GCDTest[2141:108369] 異步線程<NSThread: 0x7fdde8704cf0>{number = 2, name = (null)}
2015-01-10 18:34:23.584 GCDTest[2141:108369] 該線程woken<NSThread: 0x7fdde8704cf0>{number = 2, name = (null)}
5.
2015-01-10 18:34:59.629 GCDTest[2151:108851] 超時
2015-01-10 18:34:59.629 GCDTest[2151:108878] 異步線程<NSThread: 0x7ff142f276c0>{number = 2, name = (null)}
2015-01-10 18:34:59.630 GCDTest[2151:108851] 主線程<NSThread: 0x7ff142f06520>{number = 1, name = main}
2015-01-10 18:34:59.630 GCDTest[2151:108878] 該線程woken<NSThread: 0x7ff142f276c0>{number = 2, name = (null)}
第四種狀況主線程沒有遇到dispatch_semaphore_wait以前讓主線程睡5秒鐘。
dispatch_queue_t queue = dispatch_queue_create("My_QUEUE", NULL);//建立一個隊列 dispatch_semaphore_t sema = dispatch_semaphore_create(0);//建立一個信號量 dispatch_async(queue, ^{ //異步執行一個線程 NSLog(@"異步線程%@",[NSThread currentThread]); long int threadState = dispatch_semaphore_signal(sema); //得到該block是否被執行的狀態 if (threadState) { NSLog(@"該線程unwoken%@",[NSThread currentThread]); }else{ NSLog(@"該線程woken%@",[NSThread currentThread]); } }); [NSThread sleepForTimeInterval:5];//睡5秒鐘 long int state = dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 1)); if(state){ //判斷時超時了仍是正常的執行完成超時時間爲10 億分之 1秒 NSLog(@"超時"); }else{ NSLog(@"執行成功"); } NSLog(@"主線程%@",[NSThread currentThread]);
1:
2015-01-10 18:46:55.760 GCDTest[2304:113183] 異步線程<NSThread: 0x7faa117142d0>{number = 2, name = (null)}
2015-01-10 18:46:55.761 GCDTest[2304:113183] 該線程woken<NSThread: 0x7faa117142d0>{number = 2, name = (null)}
//相差5秒鐘
2015-01-10 18:47:00.761 GCDTest[2304:113117] 執行成功
2015-01-10 18:47:00.761 GCDTest[2304:113117] 主線程<NSThread: 0x7faa11414140>{number = 1, name = main}
主線程沒有遇到 dispatch_semaphore_wait函數就睡着了,因而異步線程執行,異步線程執行完成以後主線程繼續執行,因此輸出結果不變。
第五種使用狀況:
dispatch_semaphore_signal函數在任務開始前調用
<pre name="code" class="objc">dispatch_queue_t queue = dispatch_queue_create("My_QUEUE", NULL);//建立一個隊列 dispatch_semaphore_t sema = dispatch_semaphore_create(0);//建立一個信號量 dispatch_async(queue, ^{ //異步執行一個線程 dispatch_semaphore_signal(sema);//在循環以前 for (int i=0; i<4; i++) { NSLog(@"異步線程%@",[NSThread currentThread]); } }); long int state = dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 1000000000)); if(state){ //判斷時超時了仍是正常的執行完成超時時間爲10 億分之 1秒 NSLog(@"超時"); }else{ NSLog(@"執行成功"); } NSLog(@"主線程%@",[NSThread currentThread]);
運行結果:
1.<p class="p1"><span class="s1"><strong>2015-01-10 19:05:34.610 GCDTest[2599:121079] </strong></span><span class="s2"><strong>異步線程</strong></span><span class="s1"><strong><NSThread: 0x7ff258718d00>{number = 2, name = (null)}</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:34.610 GCDTest[2599:121044] </strong></span><span class="s2"><strong>執行成功</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:34.611 GCDTest[2599:121044] </strong></span><span class="s2"><strong>主線程</strong></span><span class="s1"><strong><NSThread: 0x7ff258600370>{number = 1, name = main}</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:34.611 GCDTest[2599:121079] </strong></span><span class="s2"><strong>異步線程</strong></span><span class="s1"><strong><NSThread: 0x7ff258718d00>{number = 2, name = (null)}</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:34.611 GCDTest[2599:121079] </strong></span><span class="s2"><strong>異步線程</strong></span><span class="s1"><strong><NSThread: 0x7ff258718d00>{number = 2, name = (null)}</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:34.611 GCDTest[2599:121079] </strong></span><span class="s2"><strong>異步線程</strong></span><span class="s1"><strong><NSThread: 0x7ff258718d00>{number = 2, name = (null)}</strong></span></p><p class="p1"><span class="s1"><strong>2.</strong></span></p><p class="p1"><span class="s1"><strong></strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:57.101 GCDTest[2607:121357] </strong></span><span class="s2"><strong>執行成功</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:57.102 GCDTest[2607:121395] </strong></span><span class="s2"><strong>異步線程</strong></span><span class="s1"><strong><NSThread: 0x7fb4c3721a50>{number = 2, name = (null)}</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:57.102 GCDTest[2607:121395] </strong></span><span class="s2"><strong>異步線程</strong></span><span class="s1"><strong><NSThread: 0x7fb4c3721a50>{number = 2, name = (null)}</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:57.102 GCDTest[2607:121357] </strong></span><span class="s2"><strong>主線程</strong></span><span class="s1"><strong><NSThread: 0x7fb4c3707140>{number = 1, name = main}</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:57.103 GCDTest[2607:121395] </strong></span><span class="s2"><strong>異步線程</strong></span><span class="s1"><strong><NSThread: 0x7fb4c3721a50>{number = 2, name = (null)}</strong></span></p><p class="p1"><span class="s1"><strong>2015-01-10 19:05:57.103 GCDTest[2607:121395] </strong></span><span class="s2"><strong>異步線程</strong></span><span class="s1"><strong><NSThread: 0x7fb4c3721a50>{number = 2, name = (null)}</strong></span></p>3.
2015-01-10 19:06:14.510 GCDTest[2612:121617] 異步線程<NSThread: 0x7fc2ab683410>{number = 2, name = (null)}
2015-01-10 19:06:14.510 GCDTest[2612:121591] 執行成功
2015-01-10 19:06:14.511 GCDTest[2612:121617] 異步線程<NSThread: 0x7fc2ab683410>{number = 2, name = (null)}
2015-01-10 19:06:14.511 GCDTest[2612:121591] 主線程<NSThread: 0x7fc2ab610ad0>{number = 1, name = main}
2015-01-10 19:06:14.511 GCDTest[2612:121617] 異步線程<NSThread: 0x7fc2ab683410>{number = 2, name = (null)}
2015-01-10 19:06:14.511 GCDTest[2612:121617] 異步線程<NSThread: 0x7fc2ab683410>{number = 2, name = (null)}
運行結果分析:老是運行成功的由於你經過dispatch_semaphore_signal把信號傳出去了,主線成就知道執行完成,尚未等待10秒鐘就開始運行了,這時主線程獲得運行時間片,而異步線程就掛起,以後就是通常的異步執行了。
第六種使用狀況:dispatch_semaphore_signal在循環後面調用
dispatch_queue_t queue = dispatch_queue_create("My_QUEUE", NULL);//建立一個隊列 dispatch_semaphore_t sema = dispatch_semaphore_create(0);//建立一個信號量 dispatch_async(queue, ^{ //異步執行一個線程 for (int i=0; i<4; i++) { NSLog(@"異步線程%@",[NSThread currentThread]); } dispatch_semaphore_signal(sema);//在循環以後 }); long int state = dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 1000000000)); if(state){ //判斷時超時了仍是正常的執行完成超時時間爲10 億分之 1秒 NSLog(@"超時"); }else{ NSLog(@"執行成功"); } NSLog(@"主線程%@",[NSThread currentThread]);
運行結果:
運行結果:
2015-01-10 19:09:33.073 GCDTest[2630:122603] 異步線程<NSThread: 0x7fe7a94090e0>{number = 2, name = (null)}
2015-01-10 19:09:33.073 GCDTest[2630:122603] 異步線程<NSThread: 0x7fe7a94090e0>{number = 2, name = (null)}
2015-01-10 19:09:33.073 GCDTest[2630:122603] 異步線程<NSThread: 0x7fe7a94090e0>{number = 2, name = (null)}
2015-01-10 19:09:33.074 GCDTest[2630:122603] 異步線程<NSThread: 0x7fe7a94090e0>{number = 2, name = (null)}
2015-01-10 19:09:33.074 GCDTest[2630:122560] 執行成功
2015-01-10 19:09:33.074 GCDTest[2630:122560] 主線程<NSThread: 0x7fe7a970fe80>{number = 1, name = main}
結果分析:由於dispatch_semaphore_signal在循環以後,主線程就等待,當循環執行完成以後調用<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;">dispatch_semaphore_signal通知主線程任務執行完成,因而主線才執行,若是等了10秒鐘尚未收到信號,它就會按照超時處理。</span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"><span style="white-space:pre"> </span>總結:在程序設計時要把握信號的發送時間,由於信號是告訴別人你完成了,若是沒有完成就發送信號,別的線程就會認爲是完成而不是超時,編程中主要注意信號發送和等待的時間設置。</span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"><span style="white-space:pre"> </span>文明轉載評論是對本身的尊重和對學者的鼓勵,歡迎討論指正。</span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-size: 13.3333339691162px; font-family: Arial, Helvetica, sans-serif;"> </span>