NSThread基本概念
-
一個(gè)NSThread對(duì)象就是代表一條線程
- 一個(gè)NSThread線程對(duì)象都可以有它對(duì)應(yīng)的名字和編號(hào)(number).
- 名字可以通過(guò)NSThread的
name
屬性來(lái)設(shè)置
- 編號(hào)(number)是不能設(shè)置的,一般由系統(tǒng)決定,但主線程默認(rèn)就是1,只要不為1的就是子線程
- 線程是有調(diào)度優(yōu)先級(jí)的,取值范圍(0.0~1.0),默認(rèn)為0.5,取值越大,優(yōu)先級(jí)越大.通過(guò)
threadPriority
屬性來(lái)設(shè)置優(yōu)先級(jí)
-
線程的狀態(tài)(生命周期)
- 1>新創(chuàng)建一個(gè)線程是,線程是處于新建狀態(tài)
- 2>啟動(dòng)線程之后,線程就處于就緒狀態(tài),并且會(huì)把線程放入CPU中得可調(diào)度線程池中
- 3>當(dāng)CPU調(diào)度到線程之后,線程就處于運(yùn)行狀態(tài).CPU調(diào)度其他線程話,線程又會(huì)處于就緒狀態(tài).(所以說(shuō)線程會(huì)在就緒狀態(tài)和運(yùn)行狀態(tài)間來(lái)回切換)
- 4>當(dāng)線程被sleep或遇到鎖的時(shí)候,線程會(huì)處于阻塞狀態(tài),并且會(huì)把線程移出CPU中的可調(diào)度線程池.
- 5>當(dāng)線程sleep完或鎖解開的時(shí)候,會(huì)把線程放回CPU中的可調(diào)度線程池,繼續(xù)在就緒狀態(tài)和運(yùn)行狀態(tài)間來(lái)回切換
- 6>線程中的任務(wù)執(zhí)行完畢或者異常/強(qiáng)制退出的時(shí)候,系統(tǒng)就會(huì)把線程release(釋放掉).
-
在啰嗦一次,任何和UI相關(guān)的操作必須在主線程中執(zhí)行.
廢話不多說(shuō),上代碼
//
// ViewController.m
//
// Created by 雨軒 on 16/1/23.
// Copyright ? 2016年 apple. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
/**
* 屏幕觸摸事件
*
*/
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//獲取當(dāng)前線程
NSThread * currentThread = [NSThread currentThread];
//判斷調(diào)用此方法的線程對(duì)象 是否是主線程
// [currentThread isMainThread];
//判斷當(dāng)前線程是否是主線程
// [NSThread isMainThread];
//打印結(jié)果發(fā)現(xiàn)當(dāng)前線程是主線程
//前面說(shuō)過(guò): 和UI相關(guān)操作都必須放在主線程中.屏幕觸摸也屬于UI相關(guān)操作
NSLog(@"當(dāng)前線程: %@",currentThread);
//獲取主線程
NSThread * mainThread = [NSThread mainThread];
//打印當(dāng)前線程 和主線程
//打印結(jié)果發(fā)現(xiàn)兩個(gè)內(nèi)存地址是一樣的: 由此可證明一個(gè)進(jìn)程里有且只會(huì)有一條主線程
NSLog(@"%@ ====== %@",currentThread, mainThread);
[self createNSThreadOne];
// [self createNSThreadTwo];
// [self createNSThreadThree];
//線程間的通信
//在子線程中下載圖片
//給imageView設(shè)置圖片也數(shù)據(jù)UI操作,所以必須在主線程中設(shè)置
//就得在子線程中告訴主線程,讓它去設(shè)置圖片
[NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:self withObject:nil];
}
//耗時(shí)操作
-(void)operate:(NSString *)object{
NSLog(@"%@",object);
NSThread * currentThread = [NSThread currentThread];
for(int i = 0; i < 50000 ; i++){
//讓當(dāng)前線程睡眠2秒
//[NSThread sleepForTimeInterval:2.0];
//讓當(dāng)前線程睡眠到指定時(shí)間
//NSDate * date = [NSDate dateWithTimeIntervalSinceNow:2.0]; //獲取當(dāng)前時(shí)間后兩秒的時(shí)間
//[NSThread sleepUntilDate:date];
NSLog(@"%d========%@",i,currentThread);
if(i == 30){
NSLog(@"線程強(qiáng)制退出");
//強(qiáng)制退出當(dāng)前線程(線程進(jìn)入死亡狀態(tài)),線程不在執(zhí)行任何任務(wù)
//如果在鎖內(nèi)使用,會(huì)把鎖內(nèi)所有子線程退出
[NSThread exit];
}
}
//如果執(zhí)行了[NSThread exit] 就不會(huì)執(zhí)行這行代碼了
// 就相當(dāng)于 return 出這個(gè)方法了.
NSLog(@"任務(wù)執(zhí)行完畢");
}
//NSThread 創(chuàng)建子線程方式一
-(void)createNSThreadOne{
/*
創(chuàng)建一個(gè)子線程: 此創(chuàng)建方式需要手動(dòng)啟動(dòng)線程
參數(shù)說(shuō)明:
第一個(gè)參數(shù): 目標(biāo)對(duì)象
第二個(gè)參數(shù): 執(zhí)行目標(biāo)對(duì)象中那個(gè)方法
第三個(gè)參數(shù): 執(zhí)行方法需要傳入的參數(shù), 沒有參數(shù)寫nil即可
*/
//從代碼上來(lái)看,好像這個(gè)線程是個(gè)局部變量,看起來(lái)好像方法執(zhí)行完之后就會(huì)銷毀這個(gè)局部線程
//其實(shí)并不會(huì),因?yàn)槿绻趫?zhí)行系統(tǒng)分離出來(lái)的子線程的話,系統(tǒng)內(nèi)部會(huì)retain一次
//只有線程中的方法執(zhí)行完畢之后,系統(tǒng)會(huì)自動(dòng)release(釋放)掉此子線程
NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(operate:) object:@"AAA"];
//設(shè)置線程名稱
thread.name = @"線程AAA";
//設(shè)置線程優(yōu)先級(jí)(0.0~0.1)
thread.threadPriority = 0.7;
//啟動(dòng)線程
[thread start];
}
//NSThread 創(chuàng)建子線程方式二
-(void)createNSThreadTwo{
/*
創(chuàng)建一個(gè)子線程: 此方法創(chuàng)建線程無(wú)需手動(dòng)啟動(dòng), 系統(tǒng)創(chuàng)建好之后會(huì)自動(dòng)啟動(dòng)線程
缺點(diǎn): 無(wú)法詳細(xì)設(shè)置線程
*/
[NSThread detachNewThreadSelector:@selector(operate:) toTarget:self withObject:@"BBB"];
}
//NSThread 創(chuàng)建子線程方式三
-(void)createNSThreadThree{
//使用此方法,系統(tǒng)會(huì)自動(dòng)創(chuàng)建一個(gè)子線程,然后在子線程中調(diào)用此方法
//特點(diǎn):自動(dòng)啟動(dòng)線程,但不能詳細(xì)設(shè)置線程
[self performSelectorInBackground:@selector(operate:) withObject:@"CCC"];
}
//線程間的通信
-(void)downloadImage{
//圖片地址
NSURL * imageUrl = [NSURL URLWithString:@"http://www.xxjxsj.cn/article/UploadPic/2009-8/2009810023722867.jpg"];
//加載圖片數(shù)據(jù)
NSData * imageData = [NSData dataWithContentsOfURL:imageUrl];
//創(chuàng)建圖片
UIImage * image = [UIImage imageWithData:imageData];
NSLog(@"%@",[NSThread currentThread]);
//通信方式一
//指定對(duì)象的方法在主線程中調(diào)用,這里用了個(gè)小技巧 直接調(diào)用了imageView中的 setImage: 方法
///waitUntilDone:是否等待執(zhí)行完成
[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
//通信方式二
//指定對(duì)象的某個(gè)方法去指定的線程里執(zhí)行
//waitUntilDone:是否等待執(zhí)行完成
//[self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
}
@end
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。