溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

iOS使用多線程提高數(shù)據(jù)并發(fā)訪問(wèn) 之五

發(fā)布時(shí)間:2020-07-06 10:47:03 來(lái)源:網(wǎng)絡(luò) 閱讀:760 作者:iKingLai 欄目:移動(dòng)開發(fā)

你的線程入口


當(dāng)啟動(dòng)線程時(shí),你需要有一些代碼來(lái)管理當(dāng)前線程的狀態(tài),線程創(chuàng)建和執(zhí)行的內(nèi)存,還有在線程內(nèi)部拋出的異常。原因是你新創(chuàng)建的線程會(huì)有自己的棧,它和默認(rèn)的棧是不同的,如圖 6-4。因此,你線程使用的內(nèi)存和主線程使用的內(nèi)存是不同的。異常也類似;它只會(huì)存儲(chǔ)在你的棧中,并不會(huì)返回到主棧和主線程中。


iOS使用多線程提高數(shù)據(jù)并發(fā)訪問(wèn) 之五

有很多事情你需要記?。?br />

  • Autorelease pool:管理autorelease對(duì)象

  • ExceptionHandler:管理線程運(yùn)行過(guò)程中發(fā)生的異常

  • RunLoop:創(chuàng)建事件處理代碼


我會(huì)討論為什么要實(shí)現(xiàn)他們已經(jīng)如何實(shí)現(xiàn)他們。


表格6-3 提供了一個(gè)簡(jiǎn)短的演示,讓你復(fù)習(xí)一下創(chuàng)建和配置線程的主要技術(shù),以及他們的優(yōu)缺點(diǎn)。

iOS使用多線程提高數(shù)據(jù)并發(fā)訪問(wèn) 之五

Autorelease Pool


在應(yīng)用的每一個(gè)線程中,你應(yīng)該總是要有一個(gè)Autorelease Pool,通過(guò)把代碼放在@autorelease中塊中。這個(gè)pool會(huì)包含所有的autoreleased對(duì)象,當(dāng)線程運(yùn)行的時(shí)候。如果你沒(méi)有調(diào)用返回一個(gè)autoreleased對(duì)象的方法,最好還是包含@autorelease,因?yàn)橄到y(tǒng)底層的frameworks和libraries也會(huì)創(chuàng)建和返回autoreleased對(duì)象。如果你有一個(gè)@autorelease,而從沒(méi)使用它,一切依然能夠正常運(yùn)行。


如果你通過(guò)Xcode模板創(chuàng)建的應(yīng)用,你會(huì)看到main方法中有下面的代碼:


int main(int argc, char *argv[]) {

   @autoreleasepool {

           int retVal = UIApplicationMain(argc, argv, nil, nil);

   }

   return retVal;

}


@autorelease將會(huì)處理線程內(nèi)部所有的autoreleased對(duì)象。你可能已經(jīng)知道,autoreleased對(duì)象是

一個(gè)你不再使用的,但是你又不想立即釋放的對(duì)象。它同樣可以使用類似[NSMutableArray array]這樣的工廠方法來(lái)返回一個(gè)autorelease對(duì)象;。這些對(duì)象將在run loop結(jié)束時(shí)被release。


因此,如果你創(chuàng)建了一個(gè)新的線程,確保你的代碼包裹在@autorelease塊中,像這樣:


- (void)myThreadMethod {

       @autoreleasepool { // Top-level pool

       // Do thread work here.

       }

}


ExceptionHandler


在處理線程時(shí),異常是非常重要的。因?yàn)槊恳粋€(gè)線程都有它自己的棧,當(dāng)發(fā)生一個(gè)異常時(shí),它將會(huì)跟蹤所有的方法直到棧的頂部。這可能導(dǎo)致你的線程停止運(yùn)行。任何主線程中的exception handler將會(huì)被忽略。


下面是一個(gè)處理異常的基本代碼:


NSObject *myObject = nil;

@try {

   // access to some objects inside an array

   myObject = [myArray objectAtIndex:2];

}

@catch ( NSException *e ) {

       NSLog(@"Array has fewer than 3 items");

}

@finally {
       // clean up code here

}


Run Loop


當(dāng)你創(chuàng)建一個(gè)新的線程后,你有兩種方法來(lái)執(zhí)行它。

  • 在線程內(nèi)部編寫代碼來(lái)執(zhí)行你的邏輯,直到任務(wù)執(zhí)行完畢,而沒(méi)有什么中斷。比如,之前介紹過(guò)的從URL現(xiàn)在圖片的代碼。顯然,這是比較簡(jiǎn)單的。

  • 當(dāng)有動(dòng)態(tài)事件發(fā)生時(shí),你想要你的線程做出響應(yīng)。比如監(jiān)聽網(wǎng)絡(luò)上的socket或在某個(gè)特定時(shí)間觸發(fā)的事件。這和第一種情況是不同的,需要你在創(chuàng)建一個(gè)新的run loop。


下面是一個(gè)簡(jiǎn)單的代碼,在一個(gè)RunLoop中監(jiān)聽一個(gè)輸入流:


  1. NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    [iStream setDelegate:self];
    [iStream scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode];



注意:如果[NSRunLoop currentRunLoop]方法是在一個(gè)線程中調(diào)用,而不是一個(gè)run loop,這個(gè)方法創(chuàng)建一個(gè)新的run loop。



如果你想要在開始運(yùn)行之前,讓一個(gè)run loop來(lái)等待一段時(shí)間,你可以使用NSTimer:


  1. [NSTimer scheduledTimerWithTimeInterval:2.0target:self

    selector:@selector(doStuff)userInfo:nil

    repeats:YES];


但是,有些情況你不應(yīng)該使用RunLoop,比如在主線程中你有事件處理代碼,如NSInputStream或NSTimer工作在一些敏感的任務(wù)上,要花費(fèi)很長(zhǎng)的時(shí)間才能完成。因?yàn)槭录幚泶a,像我的這個(gè)例子,最終會(huì)運(yùn)行在創(chuàng)建它的線程上,你的線程不能繼續(xù)運(yùn)行其他事件處理代碼,直到舊的事件處理完畢。這對(duì)UI主線程是非常有害的,如果你在線程內(nèi)部創(chuàng)建了timer或input stream run loop。主要的問(wèn)題是它使得你的UI變得更不靈敏。





向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI