你對多線程的理解有多少??

爲何要使用多線程? 學習多線程的目的: 將耗時操做放到後臺去執行, 這也是學習多線程最主要的目的!
那麼怎樣能看出哪些操做是耗時較多的呢,這裏咱們就來模擬一下內存幾個區不一樣的耗時狀況:
git

假設有一個新聞類的app,若是咱們按照在UI階段的方法,使用plist加載本地數據,那麼這個app上的數據都是死的,用戶看來看去都是固定死的幾條「新聞」,最終的結果就是,用戶會刪掉這個app。 沒有數據的app猶如一潭死水,沒有生機!那麼,怎麼來實時地獲取數據呢?只有經過網絡從遠程服務器的數據庫中獲取實時數據。這樣咱們的app纔可以保持活力! 可是,從網絡上獲取數據的時候會存在一個問題,比方說:下載一個小電影,一般是比較消耗時間的。也就是說,從網絡上獲取數據的操做屬於耗時操做。 那麼,耗時操做會對咱們的app產生什麼影響呢?給你們提示一下,既然咱們如今要學習多線程,那就說明咱們以前寫的全部代碼都是在單線程上執行的。這裏給你們舉個例子,過河,若是把河上的橋比做線程,那麼咱們以前都是在走獨木橋。走獨木橋有什麼特色呢?假設有10我的要過河,可是第1我的張三跟人打架,腿瘸了,那麼張三過橋就會很是墨跡。後面的人想過橋,沒門,必須等張三過去了,後面的人才能夠過河。 這個例子放到程序裏面,就是網絡操做比較耗時,若是網絡操做沒有執行完畢,用戶的其它操做就會被阻塞,結果就是用戶會感到很是卡頓,而後就是各類刪刪刪了。 而多線程就是專門用來解決這種問題的!github

因此在引入多線程以前,咱們先來作一個模擬耗時操做的演練。數據庫

一、代碼一:循環測試

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 單線程
    [self demo];
}

#pragma mark - 模擬耗時操做

- (void)demo {
    
    NSLog(@"bengin");
    for (int i = 0; i < 10000000; i++) {
        
    }
    NSLog(@"end");
}

打印臺輸出結果爲:服務器

輸入圖片說明

經過輸出結果可知:循環的速度很是很是快; 僅爲0.025s

二、代碼二:操做內存的棧空間

-	(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
// 單線程
    [self demo];
}
#pragma mark - 模擬耗時操做
- (void)demo {
    NSLog(@"bengin");
    for (int i = 0; i < 10000000; i++) {
        int n = i;
    }
    NSLog(@"end");
}

打印臺輸出結果爲:網絡

輸入圖片說明

經過輸出結果可知:操做內存的棧空間,速度一樣很是快。僅爲 0.026s

三、代碼三:操做內存的常量區

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 單線程
    [self demo];
}
#pragma mark - 模擬耗時操做

- (void)demo {
    
    NSLog(@"bengin");
    for (int i = 0; i < 10000000; i++) {
        // 使用@""定義的字符串保存在常量區
        NSString *str = @"hello";
    }
    NSLog(@"end");
}

打印臺輸出結果爲:多線程

輸入圖片說明

經過輸出結果可知: 操做內存的常量區, 速度比較快(比操做棧區稍微慢點) 0.099s

四、代碼四:操做內存的堆空間

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 單線程
    [self demo];
}
#pragma mark - 模擬耗時操做

- (void)demo {
    NSLog(@"bengin");
    for (int i = 0; i < 10000000; i++) {
        // 使用 stringWithFormat 拼接的字符串保存在堆區
        NSString *str = [NSString stringWithFormat:@"hello - %d", i];
    }
    NSLog(@"end");
}

打印臺輸出結果爲:app

輸入圖片說明

經過輸出結果可知:操做內存的堆空間,速度比操做常量區慢;循環很是消耗CPU資源: 時間爲10.597s

五、代碼五:I/O操做

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 單線程
    [self demo];
}
#pragma mark - 模擬耗時操做

- (void)demo {
    NSLog(@"bengin");
    for (int i = 0; i < 10000000; i++) {
        // I/O操做
        NSLog(@"%d", i);
    }
    NSLog(@"end");
}

打印臺輸出結果爲:學習

輸入圖片說明

從輸出結果可知:I/O操做,速度很是慢。

六、代碼六:引入多線程技術

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 多線程
    [self performSelectorInBackground:@selector(demo) withObject:nil];
}
#pragma mark - 模擬耗時操做
- (void)demo {
    
    NSLog(@"bengin");
    for (int i = 0; i < 10000000; i++) {
        // I/O操做
        NSLog(@"%d", i);
    }
    NSLog(@"end");
}

打印臺輸出結果爲:測試

輸入圖片說明

由輸出結果可知:引入多線程技術以後,即使是I/O操做這種耗時操做,也不會形成程序卡頓。

七、小結與思考

小結:

(1) 耗時操做的後果:若是隻有主線程,會形成程序卡頓,用戶體驗極差。
(2) 學習多線程的目的:將耗時操做放到後臺線程去執行。
(3) 經過耗時操做演練可知,操做效率的順序:

I/O操做 < 堆區 < 常量區 < 棧區。線程

(4) 使用@」」定義的字符串保存在常量區,使用stringWithFormat拼接的字符串保存在堆區。
(5) 網絡操做也屬於耗時操做,經過多線程技術能夠將耗時的網絡操做放到後臺線程去執行,從而提升程序執行效率,改善用戶體驗。
(6) - (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg 在後臺執行某方法。

思考:

#####(1)耗時操做會對咱們的應用程序產生什麼影響? 耗時操做的後果:在主線程,耗時操做會形成程序卡頓,用戶會覺得程序死了,用戶體驗極差。 #####(2)耗時操做形成的程序卡頓問題該怎麼解決? 要想解決程序卡頓問題,就須要使用多線程技術,將耗時操做放到子線程去執行。

綜上所述,就能夠看出多線程在咱們實際開發中,是多麼的重要!!!

更多內容請關注個人GitHub項目: https://github.com/DXSmile/Multi-Thread-

相關文章
相關標籤/搜索