IOS多線程二 NSThread簡約而不簡單

IOS多線程二NSThread簡約而不簡單

今天就來著手教大家在IOS中簡單的實現(xiàn)多線程箱舞。IOS實現(xiàn)多線程的方式有幾種督函,但是要說最容易上手的還是NSThread,在IOS實現(xiàn)多線程的幾種方法中提针,在我看來其實沒有明顯的好壞之分藕甩,只有適合之說施敢,看何種場景下適合使用何種方式。

NSThread相對來說更加輕量級狭莱,并且更加具體僵娃,沒有那么抽象,一個線程就是一個類的對象腋妙。你可以給這個對象附上需要執(zhí)行的內(nèi)容默怨,其實也就是一個方法,可以通過調(diào)用該類的相關方法骤素,控制其啟動匙睹、關閉、暫停等济竹。好吧痕檬,這里就不多說了,下面著重看下NSThread這個類送浊。

直接在Xcode中就可以進入到NSThread類的.h文件中梦谜。可以看到NSThread是一個NSObject類的子類袭景,是IOS開發(fā)的一個重要子框架Foundation框架中的一個類唁桩。進入NSThread類的.h文件可以看到一些NSThread比較常見的方法和屬性。如下所述:

1.NSThread的init方法浴讯。

- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullableid)argumentNS_AVAILABLE(10_5,2_0);

該方法主要是用一個目標對象的方法來創(chuàng)建一個多線程NSThread類。其中target參數(shù)傳遞目標對象蔼啦,selector參數(shù)傳遞目標對象的一個方法榆纽,其實就是多線程需要執(zhí)行的內(nèi)容。argument可以傳遞一個臨時參數(shù)到多線程執(zhí)行的方法中捏肢。

2.Start方法

該方法是控制線程啟動執(zhí)行的方法奈籽。init方法創(chuàng)建的NSThread對象,只有調(diào)用該方法才能啟動執(zhí)行鸵赫。

3.detachNewThreadSelector方法

+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullableid)argument;

該方法與init方法類似衣屏,參數(shù)也是一樣,區(qū)別就在于辩棒,init方法初始化好一個多線程對象之后狼忱,需要調(diào)用start方法啟動執(zhí)行膨疏,而該方法創(chuàng)建好后直接自己啟動執(zhí)行,不需要再調(diào)用start方法钻弄。并且也不會產(chǎn)生顯示的對象佃却,無法通過對象的方法來控制結(jié)束或者暫停執(zhí)行線程。

4.類方法isMultiThreaded

+ (BOOL)isMultiThreaded;

判斷當前代表執(zhí)行是否在主線程中

5.類方法currentThread

+ (NSThread*)currentThread;

獲取當前線程窘俺。

6.線程暫停方法

+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

該方法可傳遞一個秒級別的參數(shù)ti饲帅,來暫停執(zhí)行當前代碼所在的線程ti秒。

7.退出線程方法

+ (void)exit;

該方法是真正可以讓線程退出的方法瘤泪,在某個線程中調(diào)用該方法灶泵,該線程就會直接退出,之后的代碼就不會再執(zhí)行,而且要特別指出对途,該方法如果直接在主線程中調(diào)用的話赦邻,連主線程都會被直接終止哦,主線程如果都被終止了掀宋,那等于整個程序就已經(jīng)失去活力了深纲,APP都會整個卡死。

8 cancle標志方法

- (void)cancelNS_AVAILABLE(10_5,2_0);

@property(readonly,getter=isCancelled)BOOLcancelledNS_AVAILABLE(10_5,2_0);

很多初學者以為cancel就是退出線程劲妙,其實不是湃鹊,這里的cancel其實就是類中的一個BOOL型變量,用戶調(diào)用了cancel方法镣奋,該BOOL型變量就變成了真币呵,再調(diào)用isCancel就可以看到其值是YES還是NO,然后再根據(jù)該標志位做一些工作。所以對比一下退出線程還是要靠exit方法侨颈,或者直接在線程中判斷調(diào)用return退出余赢。

9 設置線程優(yōu)先級

+ (BOOL)setThreadPriority:(double)p;

@propertydoublethreadPriorityNS_AVAILABLE(10_6,4_0);// To be deprecated; use qualityOfService below

通過以上方法可以查看和設置線程優(yōu)先級,優(yōu)先級高的線程會優(yōu)先執(zhí)行哈垢,這里不建議進行此類設置妻柒,會打亂系統(tǒng)之前的線程優(yōu)先級安排≡欧郑可能造成某些底等級的線程卡頓或者長時間得不到執(zhí)行举塔。

以上大致就是NSThread類已經(jīng)類中相關的屬性和方法的基本介紹。下面就講3個具體使用NSThread實現(xiàn)多線程的例子求泰。

1.啟動一個線程

代碼示例

- (void)viewDidLoad?

{

? ? ?[super viewDidLoad];//進入某個viewController時啟動一個線程

? ? ?//使用已經(jīng)寫好的線程執(zhí)行方法FunctionForNSThread初始化一個NSThread類對象

? ? ?NSThread* nowTestThread = [[NSThread alloc] initWithTarget:self selector:@selector(FunctionForNSThread) object:nil];

? ? ?//啟動該線程類對象

? ? ?[nowTestThread start];

}

- (void)FunctionForNSThread

{

? ? ? if([NSThread isMainThread])//使用NSThread類方法isMainThread判斷當前線程是否為主線程

? ? ? {//主線程輸出信息

? ? ? ? ? ? ?NSLog(@"now is in MainThread");

? ? ? }

? ? ? else

? ? ? {//非主線程輸出信息

? ? ? ? ? ? ?NSLog(@"now is not in MainThread");

? ? ? }

}

這里的輸出結(jié)果為

2016-09-20 23:12:25.566 MultiThreadExample[622:15261] now is not in MainThread

說明我們已經(jīng)啟動了另外一個線程央渣。

2.啟動一個循環(huán)執(zhí)行的線程。

- (void)viewDidLoad?

{

? ? ?[super viewDidLoad];//進入某個viewController時啟動一個線程

? ? ?//使用已經(jīng)寫好的線程執(zhí)行方法FunctionForNSThread初始化一個NSThread類對象

? ? ?NSThread* nowTestThread = [[NSThread alloc] initWithTarget:self selector:@selector(FunctionForNSThread) object:nil];

? ? ?//啟動該線程類對象

? ? ?[nowTestThread start];

}

- (void)FunctionForNSThread

{

? ? ? intnowIndex =0;

? ? ? while(YES)//while循環(huán)執(zhí)行

? ? ? {

? ? ? ? ? ?nowIndex++;

? ? ? ? ? ?[NSThread sleepForTimeInterval:1];//每次執(zhí)行到這里讓線程暫停1秒鐘

? ? ? ? ? ?if([NSThread isMainThread])//使用NSThread類方法isMainThread判斷當前線程是否為主線程

? ? ? ? ? ?{//主線程輸出信息

? ? ? ? ? ? ? ? NSLog(@"%d now is in MainThread",nowIndex);

? ? ? ? ? ?}

? ? ? ? ? else

? ? ? ? ? {//非主線程輸出信息

? ? ? ? ? ? ? ? ? NSLog(@"%d now is not in MainThread",nowIndex);

? ? ? ? ? ?}

? ? ? }

}

該段代碼輸出結(jié)果如下:

2016-09-20 23:15:02.010 MultiThreadExample[634:16310] 1 now is not in MainThread

2016-09-20 23:15:03.016 MultiThreadExample[634:16310] 2 now is not in MainThread

2016-09-20 23:15:04.018 MultiThreadExample[634:16310] 3 now is not in MainThread

2016-09-20 23:15:05.021 MultiThreadExample[634:16310] 4 now is not in MainThread

2016-09-20 23:15:06.022 MultiThreadExample[634:16310] 5 now is not in MainThread

2016-09-20 23:15:07.023 MultiThreadExample[634:16310] 6 now is not in MainThread

2016-09-20 23:15:08.024 MultiThreadExample[634:16310] 7 now is not in MainThread

2016-09-20 23:15:09.025 MultiThreadExample[634:16310] 8 now is not in MainThread

2016-09-20 23:15:10.026 MultiThreadExample[634:16310] 9 now is not in MainThread

………

如果不強行終止程序渴频,該線程會一直執(zhí)行下去芽丹,數(shù)字編碼也會從1開始一直不斷增大。

還有一點我們在線程中使用[NSThreadsleepForTimeInterval:1];方法每次循環(huán)開始時讓線程暫停1秒鐘卜朗,大家一定要注意拔第,在這種循環(huán)執(zhí)行的線程中咕村,一定要設置循環(huán)停止時間,否則線程不斷死循環(huán)就會將設備CPU徹底占用楼肪,如果你運行的設備是雙核CPU培廓,你啟動一個不設置循環(huán)停止時間的線程,就會直接將其中一個CPU全部沾滿卡死春叫。

從上述輸出結(jié)果中也可以看到肩钠,每次輸出間隔時間都是1秒鐘。也就是說該循環(huán)執(zhí)行的內(nèi)容每隔1秒執(zhí)行一次暂殖。

3.終止一個線程

停止一個線程有很多方法价匠,初學者常犯的一個錯誤就是調(diào)用NSThread類的cancel方法。時機調(diào)用該方法并沒有作用呛每,該方法中設置的cancel只是一個標記位踩窖,調(diào)用cancel方法之后,再通過iscancel方法獲取該標記位就可以得到是否已經(jīng)cancel晨横,真正的cancel需要在該線程的執(zhí)行方法體中調(diào)用類方法exit來真正退出該線程洋腮。

- (void)viewDidLoad?

{

? ? ? [super viewDidLoad];//進入某個viewController時啟動一個線程

? ? ? //使用已經(jīng)寫好的線程執(zhí)行方法FunctionForNSThread初始化一個NSThread類對象

? ? ? NSThread* nowTestThread = [[NSThread alloc] initWithTarget:self selector:@selector(FunctionForNSThread) object:nil];

? ? ? //啟動該線程類對象

? ? ? [nowTestThread start];

? ? ? [NSThread sleepForTimeInterval:10];//主線程暫停執(zhí)行10秒鐘,這里測試需要手形,一般不建議暫停主線程啥供。

? ? ? [nowTestThread cancel];

}

- (void)FunctionForNSThread

{

? ? ? intnowIndex =0;

? ? ? while(YES)//while循環(huán)執(zhí)行

? ? ? {

? ? ? ? ? ? nowIndex++;

? ? ? ? ? ? [NSThread sleepForTimeInterval:1];//每次執(zhí)行到這里讓線程暫停1秒鐘

? ? ? ? ? ? if([NSThread isMainThread])//使用NSThread類方法isMainThread判斷當前線程是否為主線程

? ? ? ? ? ? {//主線程輸出信息

? ? ? ? ? ? ? ? ?NSLog(@"%d now is in MainThread",nowIndex);

? ? ? ? ? ? }

? ? ? ? ? ? else

? ? ? ? ? ? {//非主線程輸出信息

? ? ? ? ? ? ? ? ?NSLog(@"%d now is not in MainThread",nowIndex);

? ? ? ? ? ? }

? ? ? ? ? ?if([[NSThread currentThread] isCancelled])//先通過currentThread方法獲取當前線程,再通過isCancelled方法獲取cancel標志位

? ? ? ? ? ?{

? ? ? ? ? ? ? ? ?NSLog(@"退出線程之前");

? ? ? ? ? ? ? ? ?[NSThread exit];//cancel標志位為真库糠,說明線程外部已經(jīng)發(fā)出了終止線程的標志信號伙狐,在本線程調(diào)用exit停止線程。

? ? ? ? ? ? ? ? ?NSLog(@"退出線程之后");//該log永遠不會被打印瞬欧,因為在exit方法之后的代碼都不會再執(zhí)行

? ? ? ? ? ?}

? ? ? }

}

該段代碼執(zhí)行結(jié)果如下:

2016-09-20 23:28:37.258 MultiThreadExample[675:21235] 1 now is not in MainThread

2016-09-20 23:28:38.265 MultiThreadExample[675:21235] 2 now is not in MainThread

2016-09-20 23:28:39.267 MultiThreadExample[675:21235] 3 now is not in MainThread

2016-09-20 23:28:40.272 MultiThreadExample[675:21235] 4 now is not in MainThread

2016-09-20 23:28:41.277 MultiThreadExample[675:21235] 5 now is not in MainThread

2016-09-20 23:28:42.281 MultiThreadExample[675:21235] 6 now is not in MainThread

2016-09-20 23:28:43.283 MultiThreadExample[675:21235] 7 now is not in MainThread

2016-09-20 23:28:44.288 MultiThreadExample[675:21235] 8 now is not in MainThread

2016-09-20 23:28:45.294 MultiThreadExample[675:21235] 9 now is not in MainThread

2016-09-20 23:28:46.312 MultiThreadExample[675:21235] 10 now is not in MainThread

2016-09-20 23:28:46.312 MultiThreadExample[675:21235]退出線程之前

因為主線程在暫停10秒之后將之前啟動的線程cancel標志置為YES贷屎,而在線程內(nèi)部每次循環(huán)都會判斷cancel標志位,如果為真就調(diào)用exit退出線程艘虎,而每次循環(huán)間隔為1秒唉侄,所以執(zhí)行10次之后線程就退出了。

另外exit之后的代碼都不會被執(zhí)行野建,所以“退出線程之后”log沒有打印属划。

以上就是IOS多線程實現(xiàn)方案之一 NSThread的相關內(nèi)容,如果大家有什么心得或者不同見解可以找我溝通贬墩,QQ 1828141617 ? 郵箱 yimaoruanjian@126.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末榴嗅,一起剝皮案震驚了整個濱河市妄呕,隨后出現(xiàn)的幾起案子陶舞,更是在濱河造成了極大的恐慌,老刑警劉巖绪励,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肿孵,死亡現(xiàn)場離奇詭異唠粥,居然都是意外死亡,警方通過查閱死者的電腦和手機停做,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門晤愧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蛉腌,你說我怎么就攤上這事官份。” “怎么了烙丛?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵舅巷,是天一觀的道長。 經(jīng)常有香客問我河咽,道長钠右,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任忘蟹,我火速辦了婚禮飒房,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘媚值。我一直安慰自己狠毯,他們只是感情好,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布杂腰。 她就那樣靜靜地躺著垃你,像睡著了一般。 火紅的嫁衣襯著肌膚如雪喂很。 梳的紋絲不亂的頭發(fā)上惜颇,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音少辣,去河邊找鬼凌摄。 笑死,一個胖子當著我的面吹牛漓帅,可吹牛的內(nèi)容都是我干的锨亏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼忙干,長吁一口氣:“原來是場噩夢啊……” “哼器予!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捐迫,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤乾翔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體反浓,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡萌丈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了雷则。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辆雾。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖月劈,靈堂內(nèi)的尸體忽然破棺而出度迂,到底是詐尸還是另有隱情,我是刑警寧澤猜揪,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布英岭,位于F島的核電站,受9級特大地震影響湿右,放射性物質(zhì)發(fā)生泄漏诅妹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一毅人、第九天 我趴在偏房一處隱蔽的房頂上張望吭狡。 院中可真熱鬧,春花似錦丈莺、人聲如沸划煮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弛秋。三九已至,卻和暖如春俐载,著一層夾襖步出監(jiān)牢的瞬間蟹略,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工遏佣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留挖炬,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓状婶,卻偏偏與公主長得像意敛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子膛虫,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容