簡(jiǎn)介
大家好月而!我是Tony,一個(gè)熱愛(ài)技術(shù)汗洒,希望運(yùn)用技術(shù)改變生活的的追夢(mèng)男孩。閑話不多說(shuō)父款,今天聊聊iOS的線程币绨活。主要內(nèi)容如下:
線程焙┰埽活的運(yùn)用
線程笔郎保活的方法
保活的線程如何回收
線程迸ǘ瘢活運(yùn)用
在實(shí)際開(kāi)發(fā)中經(jīng)常會(huì)遇到一些耗時(shí)玫坛,且需要頻繁處理的工作,這部分工作與UI無(wú)關(guān)包晰,比如說(shuō)大文件的下載湿镀,后臺(tái)間隔一段時(shí)間進(jìn)行數(shù)據(jù)的上報(bào),APM中開(kāi)啟一個(gè)watch dog線程等伐憾。
線程泵愠眨活的方法
我們都知道運(yùn)用啟動(dòng)后,后開(kāi)啟一個(gè)主線程树肃,這個(gè)線程一直監(jiān)聽(tīng)這各種事件源蒸矛,這個(gè)監(jiān)聽(tīng)器就是RunLoop.對(duì)于RunLoop的原理分析,大家可以閱讀我的另一篇文章胸嘴,這里就不做具體的描述雏掠。
自定義線程
這個(gè)我創(chuàng)建了一個(gè)TYThread,內(nèi)容如下:
import "TYThread.h"
@implementation TYThread
- (void)dealloc {
NSLog(@"%s",func);
}
@end
僅重寫(xiě)了dealloc方法,下面是具體的測(cè)試代碼
MJThread *thread = [[MJThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];
//run方法
(void)run {
@autoreleasepool {
for (int i = 0; i < 100; i++) {
NSLog(@"----子線程任務(wù) %ld",(long)i);
}
NSLog(@"%@----子線程任務(wù)結(jié)束",[NSThread currentThread]);
}
}
run方法執(zhí)行完畢后劣像,TYThread的dealloc方法也執(zhí)行了乡话,說(shuō)明一般情況下開(kāi)啟線程任務(wù)后,當(dāng)任務(wù)執(zhí)行完畢后耳奕,線程就會(huì)被銷(xiāo)毀绑青,如果想讓線程不死掉的話诬像,需要為線程添加一個(gè)RunLoop,具體代碼如下:(void)run {
@autoreleasepool {
for (int i = 0; i < 100; i++) {
NSLog(@"----子線程任務(wù) %ld",(long)i);
}
NSLog(@"%@----子線程任務(wù)結(jié)束",[NSThread currentThread]);
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
// 往RunLoop里面添加Source\Timer\Observer,Port相關(guān)的是Source1事件
//添加了一個(gè)Source1闸婴,但是這個(gè)Source1也沒(méi)啥事坏挠,所以線程在這里就休眠了,不會(huì)往下走邪乍,----end----一直不會(huì)打印
[runLoop addPort:[NSMachPort port] forMode:NSRunLoopCommonModes];
[runLoop run];
NSLog(@"%s ----end----", func);
}
}
通過(guò)打印發(fā)現(xiàn)降狠,線程的dealloc方法不會(huì)執(zhí)行,NSLog(@"%s ----end----", func);也不會(huì)執(zhí)行溺欧。下面通過(guò)performSelector方法喊熟,往線程中添加任務(wù)(IBAction)start:(id)sender {
[self performSelector:@selector(doSomethingInSubThread) onThread:self.thread withObject:nil waitUntilDone:NO];
//waitUntilDone:YES 等到子線程任務(wù)執(zhí)行完再執(zhí)行下面NSLog
//NO 不用等到子線程執(zhí)行完再執(zhí)行下面NSLog(下面NSLog在主線程,test在子線程姐刁,同時(shí)執(zhí)行)
NSLog(@"123");
}
任務(wù)可以正常執(zhí)行芥牌,說(shuō)明線程一直是活著的。
蹦羰梗活的線程如何回收
添加stop的執(zhí)行方法如下:
- (IBAction)stop:(id)sender {
[self performSelector:@selector(quitRunLoop) onThread:self.thread withObject:nil waitUntilDone:NO];
}
解決循環(huán)引用問(wèn)題
//如果使用如下方式創(chuàng)建thread壁拉,self會(huì)引用thread,thread會(huì)引用self柏靶,會(huì)造成循環(huán)引用弃理。
TYThread *thread = [[TYThread alloc] initWithTarget:self selector:@selector(run) object:nil];
//需要在quitRunLoop中,進(jìn)行如下設(shè)置
- (void)quitRunLoop {
// 設(shè)置標(biāo)記為NO
self.stopped = YES;
// 停止RunLoop
CFRunLoopStop(CFRunLoopGetCurrent());
[self.thread cancel];
//解決循環(huán)引用問(wèn)題
self.thread = nil;
NSLog(@"%s %@", func, [NSThread currentThread]);
}
這樣就能釋放掉線程
作者:tonytong
鏈接:http://www.reibang.com/p/adf8bdd62487
來(lái)源:簡(jiǎn)書(shū)