在介紹NSSThread 之前,我們先來(lái)了解一下進(jìn)程和線程的概念,以便于更好的理解NSSThread。
線程:線程是用來(lái)執(zhí)行任務(wù)的,線程徹底執(zhí)行完任務(wù)A才能去執(zhí)行任務(wù)B。為了同時(shí)執(zhí)行兩個(gè)任務(wù),產(chǎn)生了多線程,線程執(zhí)行完畢就會(huì)被銷(xiāo)毀。
進(jìn)程:進(jìn)程就是在操作系統(tǒng)中運(yùn)行的程序,專(zhuān)業(yè)點(diǎn)說(shuō),進(jìn)程就是應(yīng)用程序的執(zhí)行實(shí)例;進(jìn)程不能執(zhí)行任務(wù);進(jìn)程運(yùn)行時(shí)創(chuàng)建的資源隨著進(jìn)程的終止而死亡
主線程:當(dāng)應(yīng)用程序啟動(dòng)時(shí)自動(dòng)創(chuàng)建和啟動(dòng),通常用來(lái)處理用戶(hù)的輸入并響應(yīng)各種事件和消息,主線程的終止也意味著應(yīng)用程序的結(jié)束,要保證主線程的優(yōu)先響應(yīng);
子線程:由主線程來(lái)創(chuàng)建,用來(lái)幫助主線程執(zhí)行程序的后臺(tái)處理任務(wù)。如果在線程A中又創(chuàng)建了一個(gè)線程B,在創(chuàng)建之后,這兩者就會(huì)是相互獨(dú)立的,多個(gè)子線程之間效果上可以同時(shí)執(zhí)行。
一個(gè)進(jìn)程可以有多個(gè)線程,并且所有線程都在該進(jìn)程的虛擬地址空間中,可以使用進(jìn)程的全局變量和系統(tǒng)資源。
每個(gè)線程都可以設(shè)置優(yōu)先級(jí),操作系統(tǒng)會(huì)根據(jù)線程的優(yōu)先級(jí)來(lái)安排CPU的時(shí)間,優(yōu)先級(jí)高的線程,優(yōu)先調(diào)用的幾率會(huì)更大,同級(jí)的話,執(zhí)行的先后對(duì)線程執(zhí)行的先后有影響。
在iOS中,多線程有三種方式即:NSSthread、NSOperation、GCD。這里先介紹一下NSSThread。
NSThread開(kāi)辟線程的兩種方式
第一種:創(chuàng)建手動(dòng)開(kāi)啟線程
NSThread *myThread = [[NSThread alloc]initWithTarget:self selector:@selector(thread:) object:@"樊峻峰"];
//開(kāi)啟線程
[myThread start];
-(void)thread:(NSString *)sender{
//從網(wǎng)絡(luò)加載圖片并將它轉(zhuǎn)化為DATA類(lèi)型的數(shù)據(jù)
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kUrl]];
myImage = [UIImage imageWithData:data];
[self performSelectorOnMainThread:@selector(updataUI:) withObject:myImage waitUntilDone:YES]; }
第二種:創(chuàng)建自動(dòng)開(kāi)啟線程
[NSThread detachNewThreadSelector:@selector(thread:) toTarget:self withObject:@"王文強(qiáng)"];
imageView = [[UIImageView alloc]initWithFrame:self.view.frame];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:imageView];
-(void)updataUI:(UIImage *)kimage{
imageView.image = kimage;
NSLog(@"\n方法所在的線程%@",[NSThread currentThread]);}
其他的一些方法:
獲得當(dāng)前線程 [NSThread currentThread];
NSThread *thread = [NSThread currentThread];
設(shè)置線程的名字(主線程默認(rèn)main)
thread.name = @"我是子線程";
設(shè)置線程優(yōu)先級(jí)(0~1)
[NSThread setThreadPriority:1.0];
設(shè)置線程休眠時(shí)間
[NSThread sleepForTimeInterval:2];
獲得當(dāng)前線程是不是主線程[NSThread isMainThread];
獲得當(dāng)前進(jìn)程是不是多線程[NSThread isMultiThreaded];
PS:上述imageView為全局變量
好了,了解了知識(shí)后 讓我們來(lái)使用一下吧~
eg:使用線程加載多張圖片
{
定義的全局變量
UIImage *myImage;
int imageIndex;
NSMutableArray *threadArrays;
}
- (void)viewDidLoad {
[super viewDidLoad];
imageIndex = 100;
threadArrays = [NSMutableArray array];
self.view.backgroundColor = [UIColor whiteColor];
self.edgesForExtendedLayout = UIRectEdgeNone;
//視圖
for (int row = 0; row<3; row++) {
for (int list = 0; list<2; list++) {
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(10+list*200, 10+row*200, 180, 180)];
//imageView.backgroundColor = [UIColor orangeColor];
imageView.tag = imageIndex++;
[self.view addSubview:imageView];
}
}
//多線程
for (int index = 0; index<6; index++) {
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(thread:) object:@(index)];
[thread start];
[threadArrays addObject:thread];
}
}
-(void)thread:(NSNumber *)index{
//通過(guò)線程休眠實(shí)現(xiàn) 圖片的順序的加載
[NSThread sleepForTimeInterval:[index intValue]];
NSThread *thread = [NSThread currentThread];
if (thread.isCancelled == YES) {
[NSThread exit];
}
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kUrl]];
myImage = [UIImage imageWithData:data];
//回到主線程
[self performSelectorOnMainThread:@selector(updataUI:) withObject:index waitUntilDone:YES];
}
-(void)updataUI:(NSNumber *)index{
UIImageView *myImageView =[self.view viewWithTag:[index intValue]+100] ;
myImageView.image = myImage;
//NSLog(@"\n方法所在的線程%@",[NSThread currentThread]);
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[NSThread currentThread];
NSLog(@"======%@",threadArrays);
for (NSThread *thread in threadArrays) {
if (thread.isFinished == NO) {
[thread cancel];
}
}
}