NSThread:
NSThread 是一個(gè)控制線程執(zhí)行的對(duì)象惠桃,它不如 NSOperation抽象浦夷,通過(guò)它我們可以方便的得到一個(gè)線程,并控制它刽射,但NSThread的線程之間的并發(fā)控制是需要我們自己來(lái)控制的军拟,可以通NSCondition [k?n'di??n]實(shí)現(xiàn)。
在Cocoa的框架下誓禁,通知懈息、Timer和異步函數(shù)等都有使用多線程,(待補(bǔ)充)
使用 NSThread實(shí)現(xiàn)多線程
iOS使用 NSThread 類代表線程摹恰,創(chuàng)建新的線程也就是創(chuàng)建 NSThread對(duì)象
創(chuàng)建 NSThread 線程有兩種方式:
// - (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0);//創(chuàng)建一個(gè)新的線程對(duì)象辫继。
//+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument; //創(chuàng)建并啟動(dòng)線程 (d??t?t? 分離派遣)
上面兩種方式的本質(zhì)都是將 Target對(duì)象的selector方法 轉(zhuǎn)化為 線程執(zhí)行體,其中selector方法最多可以接受一個(gè)參數(shù)俗慈,而argument(?ɑ?ɡj?m(?)nt 理由 主題)就代表傳給selector方法的參數(shù)
target對(duì)象的 selector方法體代表了線程需要完成的任務(wù)姑宽,因此相當(dāng)于把 target對(duì)象的 Selector方法轉(zhuǎn)換為線程執(zhí)行體。
啟動(dòng)線程使用 start 方法之后,該線程立即進(jìn)入就緒狀態(tài)(相當(dāng)于“等待執(zhí)行”)闺阱,并不是立即進(jìn)入運(yùn)行狀態(tài)炮车,線程啟動(dòng)后處于就緒狀態(tài),當(dāng)系統(tǒng)調(diào)度線程后酣溃,線程才會(huì)進(jìn)入運(yùn)行狀態(tài)瘦穆。
如果程序希望調(diào)用子線程的start 方法后子線程立即開(kāi)始執(zhí)行,程序可以使用 [NSThread sleepForTimeInterval:0.001];讓當(dāng)前運(yùn)行的線程(主線程)睡眠1毫秒
終止子線程
線程會(huì)以以下三種方式之一結(jié)束,結(jié)束后就處于死亡狀態(tài),
1.線程執(zhí)行體方法執(zhí)行完成,線程正常結(jié)束,
2.線程執(zhí)行過(guò)程中出現(xiàn)了錯(cuò)誤
3.直接調(diào)用NSThread類的 exit (??ks?t)方法來(lái)終止當(dāng)前正在執(zhí)行的線程赊豌;
注:當(dāng)主線程結(jié)束時(shí),其它線程不受任何影響,并不會(huì)隨著結(jié)束扛或。一旦子線程啟動(dòng)起來(lái)后,他就擁有了和主線程相同的地位,它不受主線程的影響。
當(dāng)線程正處于執(zhí)行的過(guò)程中時(shí)候碘饼,調(diào)用isExecuting (??ks??kjut 執(zhí)行)熙兔,就會(huì)返回YES ;當(dāng)線程執(zhí)行完成后,調(diào)用isFinished 方法 就會(huì)返回YES
NSThread的多線程技術(shù)悲伶,
主要是利用NSThread這個(gè)類,一個(gè)NSThread實(shí)例 代表著 一條線程
一住涉、NSthread的初始化
1> 靜態(tài)方法 類方法直接開(kāi)啟后臺(tái)線程麸锉,并執(zhí)行選擇器方法 (d??t?t? 使…分開(kāi))
//創(chuàng)建完畢后,會(huì)馬上創(chuàng)建并開(kāi)啟新的線程
+(void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
// 新建一個(gè)線程舆声,調(diào)用@selector方法
[NSThread detachNewThreadSelector:@selector(run1) toTarget:self withObject:nil];
2> 動(dòng)態(tài)方法 成員方法淮椰,在實(shí)例化線程對(duì)象之后,需要使用start執(zhí)行選擇器方法:
+(instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0);
參數(shù)解析:
selector :線程執(zhí)行的方法纳寂,這個(gè)selector最多只能接收一個(gè)參數(shù),
target:selector消息發(fā)送的對(duì)象,
argument (?ɑ?gj?m?nt): 傳給selector的唯一參數(shù),也可以是nil;
// 初始化線程
NSThread * run1Thread = [[NSThread alloc]initWithTarget:self selector:@selector(run1) object:nil];
// 設(shè)置當(dāng)前線程的優(yōu)先級(jí)(pra???r?ti 0.0 - 1.0, 1.0最高級(jí))
run1Thread.threadPriority = 0.3;
// 開(kāi)啟線程
[run1Thread start];
// (?tɑ?ɡ?t,目標(biāo))
NSThread * run2Thread = [[NSThread alloc]initWithTarget:self selector:@selector(run2) object:nil];
run2Thread.threadPriority = 1.0;
[run2Thread start];
// 隱式創(chuàng)建線程的方法
[self performSelectorInBackground:@selector(run3) withObject:nil];
// 對(duì)于NSThread的簡(jiǎn)單使用泻拦,可以用NSObject的performSelectorInBackground替代 (p??f??m 做)
// performSelectorInBackground是將run3的任務(wù)放在后臺(tái)線程中執(zhí)行
// 同時(shí)毙芜,在NSThread調(diào)用的方法中,同樣要使用autoreleasepool進(jìn)行內(nèi)存管理争拐,否則容易出現(xiàn)內(nèi)存泄露腋粥。
// 自動(dòng)釋放池
// 負(fù)責(zé)其他線程上的內(nèi)存管理,在使用NSThread或者NSObject的線程方法時(shí)架曹,一定要使用自動(dòng)釋放池
// 否則容易出現(xiàn)內(nèi)存泄露隘冲。
// @autoreleasepool { }
// 獲取當(dāng)前的線程
NSThread * current = [NSThread currentThread];
NSLog(@"=========%@",current);
// currentThread; 該方法總是返回當(dāng)前正在執(zhí)行的線程對(duì)象。
NSLog( @"++++++++%@",[NSThread currentThread]);
// 獲取主線程
NSThread * main = [NSThread mainThread];
NSLog(@"--------%@",main);
// 暫停當(dāng)前線程 暫停兩秒
[NSThread sleepForTimeInterval:2];
// 或者
NSDate * date = [NSDate dateWithTimeInterval:2 sinceDate:[NSDate date]];
[NSThread sleepUntilDate:date];
// 線程之間的通信
// 1在指定的線程上執(zhí)行的操作
[self performSelector:@selector(run4) onThread:current withObject:nil waitUntilDone:YES];
// 2在主線程上執(zhí)行的操作
[self performSelectorOnMainThread:@selector(run5) withObject:nil waitUntilDone:YES];
// 3在當(dāng)前線程執(zhí)行操作
[self performSelector:@selector(run6) withObject:nil];
for (int i = 0; i<15; i++) {
if (i == 10) {
//創(chuàng)建線程對(duì)象
NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];
//啟動(dòng)線程 必須調(diào)用start 方法啟動(dòng)線程绑雄,
[thread start];
NSLog( @"---%@,i=%d",[NSThread currentThread],i);
//創(chuàng)建并啟動(dòng)線程 直接創(chuàng)建 不會(huì)返回 NSThread 對(duì)象展辞,// d??t?t? 分離派遣
[NSThread detachNewThreadSelector:@selector(run7) toTarget:self withObject:nil];
}
}