/*
不是技術性的文章,只是記錄自己每天學習的方式
----------------------------程序猿的征途是星辰的大海
*/
[1] 何為多線程?
在多線程學習之前,很多人將進程,線程,異步,同步,串行,并發混為一談,概念混淆很嚴重,甚至在使用一些第三方類庫的時候,不知道它進行數據請求使用的是何種方式,是異步還是同步,多線程還是單線程。這里我總結了幾天來接觸的多線程方面的知識,把概念性的內容理清。
進程:在IOS系統中,經常將一個應用等任務作為一個進程。
1個進程要想執行任務,必須得有線程(每1個進程至少要有1條線程)
線程:進程的組成單位,是進程中一些多次重復使用的代碼塊
線程是進程的基本執行單元,一個進程(程序)的所有任務都在線程中執行
比如使用酷狗播放音樂、使用迅雷下載電影,都需要在線程中執行
特點:一個線程同一時刻只能執行同一任務,如果多個任務交給同一任務來完成,
那么該線程就會執行完一個任務后再去執行下個任務,直到任務全部被完成。
【多線程解釋】:
基于進程與線程的特性,我們在一個進程中可以開辟多條線程,他們可以并行(也就是時間上同步)的執行不同的任務,好比進程為項目組,線程為項目組成員。多個線程可以同時執行不同的任務,就好比項目組成員可以同時有不同的分工,如美工和程序猿有不同的項目任務。
我們需要注意的是:在單核的時代:CPU并不能同時執行多個線程!WTF!
雖然聽起來不能接受,但確實是這樣的,CPU在同一時間只能執行一個線程,之所以看起來多個線程能同時進行工作,這是因為CPU在多個線程之間來回切換的原因,如果cpu來回切換的速度夠快,就造成了多線程并發執行的假象。
多核心的時代里, 內核級結構使用搶占式的方式,將下一個線程安排在空閑的內核上,這里就不過多贅述,不論是單核還是多核心的方式,多線程都會提高對CPU工作的要求。
也因為這樣的原因,線程過多的情況下,CPU資源就會被過多的占用,處理數據和資源的速度也會下降,所以要盡量控制一個進程中多線程的個數。(默認占用內存情況為主線程占用1M,子線程占用512KB)
多線程的優點:能適當提高程序的執行效率,能適當提高資源的利用率
多線程的缺點:線程的開始和退出都是需要內存空間來支持的,程序的復雜度也被增加,
不利于閱讀理解,線程越多的時候,整個進程對CPU的開銷越大。
使用多線程需要多關注這方面的內容,不能過于隨意的開啟新線程。
[2]主線程 和次線程 (工作線程)
主線程:在每個進程中都存在一個主線程,所有的UI控件搭建和手勢拖拽以及視圖滾動等都是在主線程中實現的。
我們常常需要進行一些耗時較長的工作,如數據請求,循環獲取數據或者處理內容,這些時候,主線程會被捆綁導致整個視圖屏幕無法被點擊,出現假死的情況,這對用戶體驗是致命的,我們為了避免出現這類的情況,往往采取開辟次線程的方法
次線程:又稱為工作線程,主要作用就在于分擔主線程的任務,并可以防止屏幕假死事故。
[3]串行和并行:
串行:使用 一個線程處理多個任務時,必須按照順序一個個執行。
并發:多個線程同步執行不同的任務。
[4]NSThread 簡單的開啟多線程
對于NSThread來說,它是一種簡單的開啟多線程模式的方法。通過在主線程實例化它的對象,執行start方法(類方法初始化的NSThread對象自動執行),就可以簡單的實現一個次線程。
<1>簡單實現多線程的例子
//在視圖中創建兩個按鈕-(void)creatUIButton{ NSArray * arr=@[@"線程1",@"線程2"]; for(int i=0;i<2;i++){ UIButton * btn=[UIButton buttonWithType:UIButtonTypeCustom]; btn.frame=CGRectMake(110, 100+100*i, 100, 30); btn.tag=i+1; btn.backgroundColor=[UIColor grayColor]; [btn setTitle:arr[i] forState:UIControlStateNormal]; [btn setTitleColor:[UIColor cyanColor ] forState:UIControlStateNormal]; [btn addTarget:self action:@selector(PRessBtn:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; }}//執行按鈕的點擊事件-(void)pressBtn:(id)sender{ //搭建子線程 UIButton * btn = (UIButton *)sender; //多個線程并發工作 互不影響 if(btn.tag==1){ //1??類方法創建線程對象 /* 參數解釋:第一個參數為選擇器方法 第二個參數為方法響應者 第三個對象為傳遞的參數,為OC對象 */ NSNumber * num=@10; [NSThread detachNewThreadSelector:@selector(threadMain1:) toTarget:self withObject:num]; //使用類方法創建線程對象,不需要手動開啟線程,只要線程被創建,就會自動調用線程方法。 }else{ NSNumber * num=@10; //2??使用實例方法,創建線程對象,但必須手動開啟線程 NSThread * thread= [[NSThread alloc]initWithTarget:self selector:@selector(threadMain2:) object:num]; //手動開啟線程 [thread start]; }}//線程1執行代碼-(void)threadMain1:(NSNumber *)num{ NSLog(@"線程1 開始>>>>>>>>"); for (int i=0; i<[num intValue]; i++) { NSLog(@"線程1 >>>> i = %d",i); [NSThread sleepForTimeInterval:0.1 ]; //線程沉睡0.5秒 } NSLog(@"線程1 結束");//線程結束 就會立即退出 (消失)}//線程2執行代碼-(void)threadMain2:(NSNumber *)num{ NSLog(@"線程2 開始!-------------!"); for (int i=0; i<[num intValue]; i++) { NSLog(@"線程2 i = %d",i*1000); [NSThread sleepForTimeInterval:0.3]; //線程沉睡0.5秒 } NSLog(@"線程2 結束"); }
-------在該實例中我們先點擊線程一按鈕,隨后立即點擊線程2按鈕
如果是在主線程中執行的兩個點擊事件,它們會怎么執行了?
這個想必很多人都清楚,在點擊第一個按鈕之后,隨后點擊第二個按鈕,他們的點擊事件是依次進行的。
在按鈕1的點擊事件還沒有結束的時候,按鈕2的點擊事件不會響應。
那么如果是在次線程中執行的兩個點擊事件,它們會怎么執行了?
我們來看該實例的執行結果
可以看出在線程一的點擊事件還沒有結束的時候,點擊線程2按鈕,程序立刻開啟了線程2方法。因此,我們可以知道:
多線程不會受彼此干擾,只要從主線程開辟一個次線程,它就能獨立的完成你安排的任務。我們也可以在主線程中打印一些標志性的內容,可以看出,主線程的任務不會因為次線程在進行而終止,它會繼續執行自己的代碼而不是等待次線程結束。
新聞熱點
疑難解答