進程和線程
要使用多線程,首先需要理解進程和線程這2個概念。這裡我簡單的說一下。
所謂進程對應的是一個應用程序,負責開辟內存空間供應用程序使用,但是進程不能執行任務(指令)。一個進程至少包含一條線程,線程是程序的執行流。
•iOS程序啟動時,在創建一個進程的同時, 會開始運行一個線程,該線程被稱為主線程
•系統中的每一個進程都有自己獨立的虛擬內存空間,而同一個進程中的多個線程則共用進程的內存空間
•每創建一個新的線程,都會消耗一定內存和CPU時間
•當多個線程對同一個資源出現爭奪的時候需要注意線程安全問題
多線程的應用及使用注意事項
將耗時、輪詢或者並發需求高等任務分配到其他線程執行,並由主線程負責統一更新界面會使得應用程序更加流暢,用戶體驗更好,例如網絡請求,播放游戲的背景音樂等。
•線程使用不是無節制的
–iOS中的主線程的堆棧大小是1M
–從第二個線程開始都是512KB
–這些數值不能通過編譯器開關或線程API函數更改
注:更新UI界面,處理界面和用戶之間的交互事件一定要在主線程中處理。
iOS中的多線程技術
1.NSObject的多線程方法-對NSThread的封裝(一個NSThread對象對應一條線程)
•開啟後台線程執行任務的方法
-(void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg
•在後台線程中通知主線程執行任務的方法
–(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
•獲取線程信息
[NSThread currentThread];
•線程休眠
[NSThread sleepForTimeInterval:1.0f];
提示:
–performSelectorInBackground方法本身是在主線程中執行的,而選擇器指定的方法是在後台線程中進行的
–盡管使用performSelectorInBackground方法調用的任務可以更新UI界面,但是在實際開發中,涉及到UI界面的更新操作,還是要使用performSelectorOnMainThread方法,以避免不必要的麻煩
注:
•內存管理對於多線程非常重要
•Objective-C可以憑借@autoreleasepool使用內存資源,並需要時回收資源
•每個線程都需要有@autoreleasepool,否則可能會出現內存洩漏
2.NSThread
•創建線程方法:
1.+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
2.- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
•參數說明:
–selector:線程執行的方法,只能有一個參數,不能有返回值
–target:selector消息發送的對象
–argument:傳輸給target的唯一參數,也可以是nil
3.NSOperation/NSOperationQueue
•NSOperation的兩個子類
1.NSInvocationOperation
2.NSBlockOperation
•工作原理:
1.用NSOperation封裝要執行的操作
2.將創建好的NSOperation對象放NSOperationQueue中
3.啟動OperationQueue開始新的線程執行隊列中的操作
•注意事項:
1.使用多線程時通常需要控制線程的並發數,因為線程會消耗系統資源,同時運行的線程過多,系統會變慢
2.使用以下方法可以控制並發的線程數量:
-(void)setMaxConcurrentOperationCount:(NSInteger)cnt;
3.使用addDependency可以建立操作之間的依賴關系,設定操作的執行順序
上面的程序設置依賴關系後,只有等操作a和b都執行完,才會執行c.
4.GCD
•GCD隊列:
1.全局隊列:所有添加到主隊列中的任務都是並發執行的(可能會開啟多條線程)
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.串行隊列:所有添加到串行隊列中的任務都是順序執行的(只可能會開啟一條線程)
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
3.主隊列:所有添加到主隊列中的任務都是在主線程中執行的
dispatch_get_main_queue();
•異步操作
–dispatch_async 在其他線程執行任務,會開啟新的線程
–異步方法無法確定任務的執行順序
•
•同步操作
–dispatch_sync 在當前在線程執行任務,不開啟新的線程
–同步操作與隊列無關
–同步方法會依次執行,能夠決定任務的執行順序
–更新界面UI時,最好使用同步方法
注:同步還是異步,取決於方法名(不影響主隊列,影響全局隊列、串行隊列)。