一旦线程停止死亡了,就不能再启动。所以线程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"]; }
同步:只能在当前线程中执行任务,不具备开启新线程的能力
异步:可以在新的线程中执行任务,具备开启新线程的能力
并发:可以让多个任务并发(同时)执行,自动开启多线程。只有在异步下才有效
串行:让任务一个接一个地执行
-(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,会卡住主线程
第一种: [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中
系统会自动将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.不要把耗时的操作放在主线程,要放在子线程中执行