CPU在單位時間片裏快速在各線程之間的切換安全
優勢:bash
缺點:多線程
new
新建一個線程start
開始一個線程,線程進入就緒(runnable
)狀態Running
)狀態Running
狀態以後會出現幾種現象sleep
或等待同步鎖,從可調度線程池中移除,進入阻塞(Blocked
)狀態sleep
到時,獲取到同步鎖,從新添加回可調度線程池,再次進入就緒(Runnable
)狀態注意:start
操做不可重複,當CPU調度當前線程,進入Running
狀態時,這裏存在一個可調度線程池,會進行一系列的判斷,若是線程池裏有當前線程,會直接執行線程,若是沒有,則判斷當前線程池的大小是否小於核心線程池的大小,若是小於,則建立一個新的線程來執行;若是大於,則等待被加入到隊列等,具體能夠參考下面的線程池工做原理。併發
具體代碼看下線程的生命週期:oop
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 根據狀態來改變 - 線程
if (self.t == nil) {
// new 新建
self.t = [[NSThread alloc] initWithTarget:self.p selector:@selector(testThreadStatus) object:@100];
// 2. 啓動線程start - runnable
[self.t start];
self.t.name = @"學習線程";
}
}
- (void)testThreadStatus {
// running
for (int i = 0; i<10; i++) {
// blocked
if (i == 2) {
sleep(1);
}
}
[self.t cancel];
}
複製代碼
流程圖: 性能
在線程的生命週期中,須要考慮到當前的可調度線程池。 首先須要判斷當前線程池的大小是否小於核心線程池大小,若是是小於,則直接建立線程去執行任務;若是是大於,則沒有能力開闢新的線程去執行任務,只能依賴現有的線程,則須要判斷工做隊列是否已經滿了,若是沒有滿,則將任務push到隊列,執行任務;若是滿了,判斷線程池裏的線程是否都工做,若是沒有,則利用線程去執行任務;若是都在工做,則進入飽和策略。學習
飽和策略:ui
RejectedExecutionException
,該異常可由調用者捕獲保證線程的安全,提升性能,具體可參考iOS的鎖spa
runloop
與線程是一一對應的,一個runloop
對應一個核心的線程,爲何說是核心的,是由於runloop
是能夠嵌套的,可是核心的只能有一個,他們的關係保存在一個全局的字典裏runloop
是來管理線程的,當線程的runloop
被開啓後,線程會在執行完任務後進入休眠狀態,有了任務就會被喚醒去執行任務runloop
在第一次獲取時被建立,在線程結束時被銷燬runloop
在程序一啓動就默認建立好了runloop
是懶加載的,只有當咱們使用的時候纔會建立,因此在子線程用定時器要注意:確保子線程的runloop
被建立,否則定時器不會回調