二、
安全
一旦线程中止死亡了,就不能再启动。因此线程NSThread不能为全局变量多线程
1.第一种方法:直接建立,手动启动 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download:) object:@"www.baidu.com"]; [thread start]; 2.第二种方法:建立后当即启动 [NSThread detachNewThreadSelector:@selector(download) toTarget:self withObject:@"www.baidu.com"]; 3.第三种方法:隐式建立 //主线程 [self performSelector:@selector(download:) withObject:@"www.baidu.com"]; //子线程 [self performSelectorInBackground:@selector(download:) withObject:@"www.baidu.com"]; object是selector方法传递的参数 -(void)download:(NSString *)url { NSLog(@"download-- %@ %@",url,[NSThread currentThread]); }
延迟执行不要勇sleep,坏处:卡住主线程 1.第一种 [NSThread sleepForTimeInterval:5.0]; 2.第二种 NSDate *date = [NSDate dateWithTimeIntervalSinceNow:3.0]; [NSThread sleepUntilDate:date];
+(void)exit
+(NSThread *)mainThread; +(NSThread *)currentThread -(BOOL)isMainThread; +(BOOL)isMainThread;
在1个进程中,线程每每不是孤立存在的,多个线程之间须要常常进行通讯。体如今两个方面:一,1个线程的数据传递给另外一个线程。二,在1个线程中执行完特定任务后,转到另外一个线程继续执行任务
并发
-(void)download:(NSString *)url { NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]]; UIImage *image = [UIImage imageWithData:data]; [self performSelectorOnMainThread:@selector(pic:) withObject:image waitUntilDone:YES]; } -(void)pic:(UIImage *)image { NSLog(@"pic:%@",image); self.imageView.image = image; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self performSelector:@selector(download:) withObject:@"http://g.hiphotos.baidu.com/image/h%3D200/sign=f23ec3ed1fd8bc3ed90801cab289a6c8/7a899e510fb30f24dc189ad4ce95d143ac4b0362.jpg"]; }
同步:只能在当前线程中执行任务,不具有开启新线程的能力异步
异步:能够在新的线程中执行任务,具有开启新线程的能力async
并发:可让多个任务并发(同时)执行,自动开启多线程。只有在异步下才有效atom
串行:让任务一个接一个地执行url
-(void)asyncGlobalQueue { //得到全局的并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //第一个参数是优先级 //异步并行。自动建立多条线程 dispatch_async(queue, ^{ NSLog(@"将任务放到全局队列中执行 %@", [NSThread currentThread]); dispatch_async(queue, ^{ NSLog(@"异步并行1 %@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"异步并行2 %@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"异步并行3 %@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"异步并行4 %@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"异步并行5 %@", [NSThread currentThread]); }); }); } -(void)asyncSerialQueue { //异步串行,自动会建立线程,但只开1条 dispatch_queue_t queue = dispatch_queue_create("cn.wx", NULL); dispatch_async(queue, ^{ NSLog(@"异步串行1 %@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"异步串行2 %@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"异步串行3 %@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"异步串行4 %@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"异步串行5 %@", [NSThread currentThread]); }); } -(void)syncGlobalQueue { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //同步并行。不会建立线程,使用主线程 dispatch_sync(queue, ^{ NSLog(@"同步并行1 %@", [NSThread currentThread]); NSLog(@"同步并行2 %@", [NSThread currentThread]); NSLog(@"同步并行3 %@", [NSThread currentThread]); NSLog(@"同步并行4 %@", [NSThread currentThread]); NSLog(@"同步并行5 %@", [NSThread currentThread]); }); } -(void)syncSerialQueue { dispatch_queue_t queue = dispatch_queue_create("cn.wx", NULL); //同步串行。不会建立线程,使用主线程 dispatch_sync(queue, ^{ NSLog(@"同步并行1 %@", [NSThread currentThread]); NSLog(@"同步并行2 %@", [NSThread currentThread]); NSLog(@"同步并行3 %@", [NSThread currentThread]); NSLog(@"同步并行4 %@", [NSThread currentThread]); NSLog(@"同步并行5 %@", [NSThread currentThread]); }); }
-(void)mainQueue { dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ NSLog(@"虽然是异步,可是是在主线程执行,因此不会开线程"); }); // dispatch_sync(queue, ^{ // NSLog(@"不能在串行上使用主队列,不然会阻塞"); // }); }
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ NSLog(@"子线程进行操做"); dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"回主线程加载图片"); }); });
不要使用sleep,会卡住主线程spa
第一种: [self performSelector:@selector(down) withObject:@"abv" afterDelay:3]; 第二种: dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{ NSLog(@"xx");//回到主线程 }); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{ NSLog(@"xx");//回到子线程 });
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"xx"); })
先将须要执行的操做封装到一个NSOperation对象,一个对象就至关于GCD的一个block线程
而后将NSOperation对象添加到NSOperationQueue中code
系统会自动将NSOperationQueue中的NSOperation取出来
将取出的NSOperation封装的操做放到一条线程中执行
NSOperation是个抽象类,不具有封装的能力,必须使用它的子类
1>NSInvocationOperation
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil]; /* [operation start]; 若是直接start,那么将会在当前线程(主线程)同步执行 */ //添加操做到队列中 [queue addOperation:operation];
2>NSBlockOperation
第一种状况:同步 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载一 %@",[NSThread currentThread]); }]; [operation start]; // 若是直接start,那么将会在当前线程(主线程)同步执行 第二种状况:异步 NSBlockOperation *operation = [[NSBlockOperation alloc] init]; //operation操做添加多个操做 [operation addExecutionBlock:^{ NSLog(@"下载一 %@",[NSThread currentThread]); }]; [operation addExecutionBlock:^{ NSLog(@"下载二 %@",[NSThread currentThread]); }]; [operation addExecutionBlock:^{ NSLog(@"下载三 %@",[NSThread currentThread]); }]; [operation start]; ps:NSBlockOperation还能够直接建立使用对象 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载一 %@",[NSThread currentThread]); }];
3>自定义子类继承NSOperation
1>.基本使用
//1.建立一个队列(非主队列) NSOperationQueue *queue = [[NSOperationQueue alloc] init]; //设置最大并发数 queue.maxConcurrentOperationCount = 2; //2.建立操做 NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载图片1 -- %@",[NSThread currentThread]); }]; NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载图片2 -- %@",[NSThread currentThread]); }]; NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(down) object:nil]; //操做完后立刻执行另外一个操做 [operation1 setCompletionBlock:^{ NSLog(@"下载图片222"); }]; //操做依赖,注意不能相互依赖 [operation2 addDependency:operation1]; [operation3 addDependency:operation2]; //3.添加操做到队列中(自动异步执行任务,并发) [queue addOperation:operation1]; [queue addOperation:operation2]; [queue addOperation:operation3];
2>其余用法
[queue cancelAllOperations]; //取消队列的全部操做。也能够直接调用NSOperation的cancel [queue setSuspended:YES]; //暂停和恢复队列。yes为暂停 经常使用场景: -(void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; [queue cancelAllOperations]; } -(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { [queue setSuspended:YES]; } -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { [queue setSuspended:NO]; }
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock:^{ //1.异步下载图片 NSURL *url = [NSURL URLWithString:@"www.baidu.com"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; //2.回到主线程设置图片 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.imageView.image = image; }]; }];
self.obj = [[NSObject alloc] init]; //锁任意对象,而且须要是惟一一把,因此须要创建个全局变量对象 @synchronized(self.obj) { }
2.atomic:线程安全,须要消耗大量的资源。不建议须要
1.不要同时开太多线材(1~3条线材便可,不要超过5条)
2.线程概念
1>主线程:UI线程,显示、刷新UI界面,处理UI控件的事件
2>子线程:后台线程,异步线程
3.不要把耗时的操做放在主线程,要放在子线程中执行