思考一段代碼
我們先來看一段代碼,猜猜一下代碼的的運作結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
運作結果:
1 2 3 | |
什麼情況?派發給主隊列的任務不是在主線程上運作,跟我們平常用的和了解的完全不一樣。
不要激動,導緻這種原因最關鍵的是這行代碼dispatch_main() ,就是這貨讓主隊列的任務在非主線程運作。
這個方法蘋果官方文檔這樣解釋的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
意思是這個方法會阻塞主線程,然後在其它線程中執行主隊列中的任務,這個方法永遠不會傳回(意思會卡住主線程)
如果去掉dispatch_main()這行代碼,就會正常在主線程裡執行任務
1 2 | |
是以在主隊列的任務通常是在主線程裡執行,但是不一定,我們可以主動去執行被添加到主隊列MainQueue的任務task(也就是說我們可以主動來調用添加到主線程隊列的blocks)。可以使用以下任一個來實作:dispatch_main()、UIApplicationMain() 、CFRunLoopRun()
那我們再思考一下,主線程是否可以運作非主隊列的任務blocks嗎?答案是可以的,比如下面的代碼:
1 2 3 4 5 6 7 8 | |
執行結果:
1 2 | |
是以通過dispatch_sync()執行的block不會開辟新的線程,而是在目前的線程(即主線程)中同步執行block
runloop和queue的差別
runloop和queue的差別
runloop和queue各自維護着自己的一個任務隊列,在runloop的每個周期裡面,會檢測自身的任務隊列裡面是否存在待執行的task并且執行。但主線程的情況比較特殊,在main runloop的每個周期,會去檢測main queue是否存在待執行任務,如果存在,那麼copy到自身的任務隊列中執行
async的實作不同
在非主線程之外,runloop和queue的任務隊列是互不幹擾的,是以兩者處理任務的機制也是完全不同的。當async任務到隊列時,GCD會嘗試尋找一個線程來執行任務。由于串行隊列同時隻能與一個線程挂鈎,是以GCD會讓該線程執行完已有任務後,才執行async到隊列中的任務。
多線程的實作有以下幾種方式
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw1DdtZ2X4d3Pw8CXBVFRJxkc0IHSVJ0clJjQDNWaT9WRuFWaNhmaIlVOjFDZ3MlVXdGSmRGN1NUbkhTUDZnY4FmTQBVTxIjSXFTcY1UbGlUbPhHehlGRXhmYhl2YpRVbyoUYphmUkZ2Lcdmbw9lepJWbt9CXuNmLvd2bsFnL6lmYt12Lc9CX6MHc0RHaiojIsJye.jpg)
串行與并發
隊列和線程