iOS 多線程
1、程序跟線程
程序:
一個程式至少有一個程序,一個程序至少有一個線程、
有獨立的記憶體空間、
同一個程序中的線程,共享記憶體中的記憶體跟資源、
程序相當與一個靜态容器,裡面裝了很多活動的線程。
線程:
每一個程式都有一個主線程,程式啟動的時候建立(調用main 來啟動)、
主線程的生命周前,和應用程式是綁定的,程式退出時候,主線程也就停止了、
多線程,一個應用程式有多個線程,提高cpu的使用律,防止主線程堵塞、
任何有可能堵塞主線程的的任務都不要再主線程執行(比如網絡請求)。
程序跟線程:我覺得這樣更好了解,程序就好比我們的道路(道路相當于程序),如果隻有一個車道(車道相當于線程),車流量一多,就可能會造成道路的堵塞,萬一前面哪輛車碰撞了。整個道路就癱瘓堵塞了。這樣子話,我們就可以開辟多個車道(線程)來緩解、加速,交通狀況。當然。如果車道(線程)增多就會增加資源的耗用。這也就是多線程會損耗一定的資源。一個道路可以開辟多個車道,(一個程序,裡面可以有多個線程); ps:個人了解,歡迎糾正
2、iOS 多線程多種實作:
2.1、NSThread
// ------------------多線程第1種方式
NSThread *thread = [[NSThreadalloc]initWithTarget:self selector:@selector(thread) object:nil];
[thread start];
// ------------------多線程第2種方式
[NSThread detachNewThreadSelector:@selector(thread) toTarget:self withObject:nil];
// ------------------多線程第3種方式
[self performSelectorInBackground:@selector(thread) withObject:nil];
//回到主線程
[self performSelectorOnMainThread:@selector(thread) withObject:nil waitUntilDone:NO];
NSlog(@"1111");
waitUntilDone 等待上面方法執行後再執行下面的内容,例如:如果waitUntilDone為yes,則等待方法執行完再列印111,如果為no,就執行方法,與列印111,同步執行!
2.2、NSOperationQueue
NSOperation 是一個抽象類,用來封裝一個獨立任務的代碼與資料。不能直接使用該類,通過子類化或系統提供的子類來完成任務,NSOperationQueue是其系統提供的子類。 NSOperationQueue 用來管理operation 集合,決定他們的執行順序,當一個 operation 被添加到queue後,一旦有多餘的線程來執行這個 operation 。那麼這個 operation 就會馬上被執行。
// -------------------多線程第4種方式
//直接代碼塊方式實作
NSOperationQueue *operationQ =[[NSOperationQueue alloc]init];
[operationQ addOperationWithBlock:^{
for (int i=0; i<50; i++) {
NSLog(@"線程1111:%d",i);
} }];
// ------------------多線程第5種方式
//建立線程隊列(線程池)
NSOperationQueue *operationQ =[[NSOperationQueue alloc]init];
//線程的最大并發數,(如果有五個任務,并發為2的話,就是先執行前面兩個,前面兩個執行完一個才會輪到後面的任務執行)
operationQ.maxConcurrentOperationCount = 2;
NSInvocationOperation *inOperation =[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(thread)object:nil];
//線程的優先級
[inOperation setQueuePriority:NSOperationQueuePriorityVeryLow];
NSInvocationOperation *inOperation2 =[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(thread1)object:nil];
//線程的優先級
[inOperation2 setQueuePriority:NSOperationQueuePriorityHigh];
//如果并發數是1得話、先添加進來的先執行
[operationQ addOperation:inOperation];
[operationQ addOperation:inOperation2];
2.3、GCD(Grand central dispatch) 一個純 c 語言 寫的庫,
GCD 的優點 :
在多核的硬體上,性能更佳!
并且操作簡單,程式猿隻需要告訴GCD 你要執行什麼任務。不需要編寫任何線程管理的代碼;
如何用?
用之前先了解:
GCD 的兩個核心的概念:
1、任務:執行什麼樣的操作
2、隊列:用來存放任務的。
任務
1、同步,第一個參數要求我們放入一個隊列,第二個參數就是我們要做的任務
dispatch_sync(<#dispatch_queue_tqueue#>, <#^(void)block#>)
2、異步
dispatch_async(<#dispatch_queue_tqueue#>, <#^(void)block#>)
.同步和異步的差別
同步:在目前線程中執行
異步:在另一條線程中執行
隊列
1、并發隊列(Concurrent Dispatch Queue),多個任務同時執行
dispatch_queue_t queue =dispatch_get_global_queue(<#long identifier#>, <#unsigned longflags#>)
2、串行隊列(Serial Dispatch Queue),前一個任務執行完了,在執行下一個任務
dispatch_queue_create(<#const char *label#>,<#dispatch_queue_attr_t attr#>)
NSLog(@"主線程:%@",[NSThread mainThread]);
//(3)将同步執行,放入并發隊列中
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_sync(queue, ^{
NSLog(@"11111 ===== >%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"22222 ===== >%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"33333 ===== >%@",[NSThread currentThread]);
});
dispatch_async(dispatch_get_main_queue(), ^{
//回到主線程
});
};
//總結:不會開辟新線程,并發都失效了。。
(6)小結
說明:同步函數不具備開啟線程的能力,無論是什麼隊列都不會開啟線程;異步函數具備開啟線程的能力,開啟幾條線程由隊列決定(串行隊列隻會開啟一條新的線程,并發隊列會開啟多條線程)。
同步函數
(1)并發隊列:不會開線程
(2)串行隊列:不會開線程
異步函數
(1)并發隊列:能開啟N條線程
(2)串行隊列:開啟1條線程
3、總結:
在開發中要注意: 當你啟動新線程去執行某個任務的時候(比如,做網絡請求),最終請求結束後,要回到主線程去更新ui。 回到主線程的方式” 1、
//回到主線程
[self performSelectorOnMainThread:@selector(thread) withObject:nil waitUntilDone:NO];
NSlog(@"1111");
waitUntilDone 等待上面方法執行後再執行下面的内容,例如:如果waitUntilDone為yes,則等待方法執行完再列印111,如果為no,就執行方法,與列印111,同步執行!
2、
dispatch_async(dispatch_get_main_queue(), ^{
//回到主線程
});
感謝糾正!
ps:每天進步一點點,做一個快樂的程式猿!