NSLog(@"%@",[NSThread currentThread]);//获取当前线程,当打印的number等于1时,表明当前是主线程,大于1表明子线程
thread = [[NSThreadalloc] initWithTarget:selfselector:@selector(run1:) object:@"123"];
[NSThread detachNewThreadSelector:@selector(run2) toTarget:self withObject:nil];
3) [self performSelectorOnMainThread:@selector(test) withObject:nil waitUntilDone:NO];//跳入主线程的方法,第一个参数表明要调用的方法,第二个参数表明传的值,第三个参数表明是否等待此操做完成后再继续往下执行
5) [self performSelector:@selector(test) withObject:nil afterDelay:3];//延迟调用
NSLog(@"%@",[NSThread currentThread]);//获取当前线程,当打印的number等于1时,表明当前是主线程,大于1表明子线程
[r runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];//runMode 第一个参数表明消息方式,默认写NSDefaultRunLoopMode,第二个参数表明结束时间,通常给distantFuture,表明不可达到的将来某个时间
//* [self performSelectorOnMainThread:@selector(test) withObject:nil waitUntilDone:NO];//跳入主线程的方法,第一个参数表明要调用的方法,第二个参数表明传的值,第三个参数表明是否等待此操做完成后再继续往下执行
//* [self performSelector:@selector(test) withObject:nil];//在当前线程执行另一个方法
//*延迟调用 [self performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#>]
[self performSelector:@selector(run3) onThread:thread withObject:nil waitUntilDone:NO];//在某个线程中执行某个方法
3、 Cocoa NSOperation
优势:不须要关心线程管理,数据同步的事情,能够把精力放在本身须要执行的操做上。
NSOperation实例封装了须要执行的操做和执行操做所需的数据,而且可以以并发或非并发的方式执行这个操做。
NSOperation自己是抽象基类,所以必须使用它的子类,使用NSOperation子类的方式有2种:一种是用定义好的两个子类:NSInvocationOperation 和 NSBlockOperation,另外一种是自定义子类继承NSOperation,实现内部相应的方法
一、 NSOperation的做用:配合使用NSOperation和NSOperationQueue也能实现多线程编程取消操做
二、 NSOperation和NSOperationQueue实现多线程的具体步骤:
先将须要执行的操做封装到一个NSOperation对象中
而后将NSOperation对象添加到NSOperationQueue中
系统会⾃动将NSOperationQueue中的NSOperation取出来
将取出的NSOperation封装的操做放到⼀条新线程中执⾏
二、建立操做对象,封装要执行的任务
//NSInvocationOperation 封装操做
NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run1) object:nil];
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run1) object:nil];
三、执行操做
[operation start];
[operation1 start];
注意:操做对象默认在主线程中执行,只有添加到队列中才会开启新的线程。即默认状况下,若是操做没有放到队列queue中,都是同步执行。只有将NSOperation放到一个
四、NSBlockOperation建立操做对象
NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block操做:%@",[NSThread currentThread]);
}];
//在NSBlockOperation对象中添加一个操做,若是NSBlockOperation对象包含了多个操做,有一个是在主线中一行,其余均在子线程中执行
五、添加操做(注意添加要放在start以前)
[block addExecutionBlock:^{
NSLog(@"block操做2:%@",[NSThread currentThread]);
}];
[block addExecutionBlock:^{
NSLog(@"block操做3:%@",[NSThread currentThread]);
}];
[block addExecutionBlock:^{
NSLog(@"block操做4:%@",[NSThread currentThread]);
}];
六、执行操做
[block start ];//注意添加要放在start以前
七、NSOperationQueue:建立队列:将操做放入队列(主队列除外),默认在子线程中执行,且不须要手动start
1)NSOperationQueue的做⽤:NSOperation能够调⽤start⽅法来执⾏任务,但默认是同步执行的
若是将NSOperation添加到NSOperationQueue(操做队列)中,系统会自动异步执行NSOperation中的操做
添加操做到NSOperationQueue中,自动执行操做,自动开启线程
2)建立NSOperationQueue
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSInvocationOperation *ioperation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run2) object:nil];
八、把操做添加到队列中
1)第一种:添加以前建立的
[queue addOperation:ioperation];
2)第二种:添加的时候建立
注意:使用NSOperationQueue时,无需start
[queue addOperationWithBlock:^{
NSLog(@"block操做队列:%@",[NSThread currentThread]);
}];
九、事件的实现
-(void)run1{
NSLog(@"执行操做:%@",[NSThread currentThread]);
}
-(void)run2{
NSLog(@"队列中执行:%@",[NSThread currentThread]);
}
4、GCD 全称:Grand Central Dispatch
一、Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始以后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。
二、GCD的工做原理是:让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务
三、 GCD是基于C语言的。若是使用GCD,彻底由系统管理线程,咱们不须要编写线程代码。只需定义想要执行的任务,而后添加到适当的调度队列(dispatch queue)。GCD会负责建立线程和调度你的任务,系统直接提供线程管理
四、经常使用的方法dispatch_async
为了不界面在处理耗时的操做时卡死,好比读取网络数据,IO,数据库读写等,咱们会在另一个线程中处理这些操做,而后通知主线程更新界面。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗时的操做
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
});
});
dispatch_async开启一个异步操做,第一个参数是指定一个gcd队列,第二个参数是分配一个处理事物的程序块到该队列。
dispatch_get_global_queue(0, 0),指用了全局队列。
通常来讲系统自己会有3个队列:global_queue、current_queue(废弃)和main_queue
获取一个全局队列是接受两个参数,第一个是我分配的事物处理程序块队列优先级。分高低和默认,0为默认2为高,-2为低
五、dispatch_group_async的使用
dispatch_group_async能够实现监听一组任务是否完成,完成后获得通知执行其余的操做。这个方法颇有用,好比你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成了。
1)建立一个组
dispatch_group_t group = dispatch_group_create();
2)在一个组内提交一个代码块来执行。必须明确这个代码块属于哪一个组,必须 在哪一个派送队列上执行。
dispatch_group_async(group, queue, ^{
NSLog(@"group1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"group2--%@",[NSThread currentThread]); });
dispatch_group_async(group, queue, ^{
NSLog(@"group3--%@",[NSThread currentThread]); });
3)等待组中的任务执行完毕,回到主线程执行block回调
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"updateUi");
});
六、dispatch_barrier_async
dispatch_barrier_async是在前面的任务执行结束后它才执行,并且它后面的任务等它执行完成以后才会执行
//建立队列,第一个参数表明队列名,第二个表明串行仍是并行:DISPATCH_QUEUE_SERIAL串行 DISPATCH_QUEUE_CONCURRENT 并行
dispatch_queue_t queue = dispatch_queue_create("123", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"dispatch_async1");
});
//上一步执行结束才执行这一步
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
});
//执行完上一步才执行下一步
dispatch_async(queue, ^{
NSLog(@"dispatch_async3");
});
七、dispatch_apply
它通常都是放在dispatch_async里面(异步)。
执行某个代码片断N次
dispatch_async(dispatch_get_global_queue(0, 0), ^{
dispatch_apply(5, dispatch_get_global_queue(0, 0), ^(size_t index) {
NSLog(@"%ld",index);
});
});
八、具体代码
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageview = [[UIImageView alloc]initWithFrame:CGRectMake(10, 30, 100, 100)];
[self.view addSubview:imageview];
UIImageView *imageview1 = [[UIImageView alloc]initWithFrame:CGRectMake(30, 150, 100, 100)];
[self.view addSubview:imageview1];
UIImageView *imageview2 = [[UIImageView alloc]initWithFrame:CGRectMake(30, 270, 100, 100)];
[self.view addSubview:imageview2];
UIImageView *imageview3 = [[UIImageView alloc]initWithFrame:CGRectMake(30, 390, 100, 100)];
[self.view addSubview:imageview3];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//NSLog(@"耗时操做:%@",[NSThread currentThread]);
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"
http://www.yooyoo360.com/photo/2009-1-1/20090112132752467.jpg"]];
UIImage *image = [UIImage imageWithData:data];
//NSLog(@"---%@",image);
//返回主线程
dispatch_async(dispatch_get_main_queue(), ^{
//NSLog(@"更新UI:%@",[NSThread currentThread]);
imageview.image = image;
});
});
//组
//建立组,用于存放耗时操做
dispatch_group_t group = dispatch_group_create();
__block UIImage *image,*image1,*image2,*image3;
//将操做封装进组,第一个参数表明要存放操做的组名,第二个参数表明操做队列,block执行耗时操做
//在一个组内提交一个代码块来执行。必须明确这个代码块属于哪一个组,必须在哪一个派送队列上执行。
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
image1 = [UIImage imageWithData:data];
//NSLog(@"==%@",image1);
});
});
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
image3 = [UIImage imageWithData:data];
//NSLog(@"----%@",image);
});
//监听一组操做,第一个参数表明要监听的组名,第二个参数表明一组操做彻底结束后跳转到哪一个队列,通常跳到主线程(dispatch_get_main_queue),block执行要进行的操做(通常用来更新UI),注意:此方法在组中的全部操做执行完毕后调用
//等待组中的任务执行完毕,回到主线程执行block回调
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
imageview.image = image;
imageview1.image = image1;
imageview2.image = image2;
imageview3.image = image3;
});
}
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end