小笔记:个人使用。保证只有自己看得懂~
在iOS中开启线程有三种方式
NSThread,GCD,NSOperation
其实还有一种,pthread ,只是这种太古老了,用起来难度大,所以被忽略了
1.NSThread
开线程方式:
//打开一个线程
-(void)newThread{
//方式1:
//withObject 参数,即run 方法的参数
//[self performSelectorInBackground:@selector(run) withObject:nil];
//方式2:
//[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
//方式3: 通过创建NSThread方式
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];
thread.name = @"thread-name-01";
[thread start];
}
//执行完任务回到主线程
-(void)run{
// to do
//.....
NSLog(@"%@",[NSThread currentThread]);
//回到主线程
//方式1:
//[self performSelector:@selector(updateUI) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO];
//方式2:
[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
}
-(void)updateUI{
NSLog(@"%@",[NSThread currentThread]);
}
2. GCD
gcd执行任务:
gcd 执行任务有两个函数:
//异步
dispatch_async(dispatch_queue_t queue, dispatch_block_t block)
//同步
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block)
备注:好好理解异步、跟同步意思,所以一个任务如果交给gcd 同步函数执行任务了,都“同步”了,你说还会开启新的线程吗?
执行任务的函数里第一个参数是队列:
//主队列
//dispatch_queue_t queue = dispatch_get_main_queue();
//创建一个队列
//dispatch_queue_t queue = dispatch_queue_create("queue name", NULL);
//全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
备注:
执行任务函数跟队列如何结合使用,决定着是否有新线程开启,是否并发等。
主队列看该方法名字dispatch_get_main_queue,“main”,所以在主队列执行任务的不管采用什么执行函数,都不会开线程
所以能开线程应是异步函数,至于是否并发就取决于队列。
所以一定要在理解的基础上进行记忆,切勿死记硬背。
-(void)gcd1{
//异步任务、同步任务 (dispatch_async,dispatch_sync)
//dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)
//dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)
//=============================================================
//队列
//主队列
//dispatch_queue_t queue = dispatch_get_main_queue();
//创建一个队列
//dispatch_queue_t queue = dispatch_queue_create("queue name", NULL);
//全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSLog(@"执行任务.....%@",[NSThread currentThread]);
});
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSLog(@"执行任务.....%@",[NSThread currentThread]);
//执行任务.....<NSThread: 0x7fab9a5d2840>{number = 2, name = (null)}
//back to mainthread update
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"update.....%@",[NSThread currentThread]);
//update.....<NSThread: 0x7fab9a401720>{number = 1, name = main}
});
});
gcd功能太强大,太多了,这里只是描述了两个函数的使用,其他使用可参考这个 文档
3.NsOperation
NSOperation是一个抽象类,因此在使用时需用起两个子类
NSInvocationOperation
NSBlockOperation
与NSOperation相关的还有一个很重要的类,NSOperationQueue,根据其名字也知道用来干啥用~
对于NSInvocationOperation用起操作时,如果没有加入NSOperationQueue队列中是不会开启新线程的,其任务还是在主线程中。
-(void)test1{
//不会开启一个线程
NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run) object:nil];
[operation start];
}
-(void)run{
NSLog(@"%@",[NSThread currentThread]);
}
对于NSBlockOperation如果没有NSOperationQueue队列中,是否开启线程取决于其任务有多少个,比如如果就一个任务,就不会开启线程,如果有多个任务就会开启多个线程。
-(void)test2{
//NSBlockOperation 是否开线程取决于是否有几个任务
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"A:%@-",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"A:%@-",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"A:%@-",[NSThread currentThread]);
}];
[operation start];
}
加入队列的情况:
-(void)test3{
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run) object:nil];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run) object:nil];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//添加到队里了,会开线程,开几条线程取决于有几个任务
[queue addOperation:operation1];
[queue addOperation:operation2];
}
最后一个NSOperation知识点,就是操作依赖,比如两个线程要执行两个任务A,B;其中B任务的执行必须在A完成后,类似这种就是所谓的操作依赖,NSOperation可用起addDependency进行处理
//操作依赖
-(void)test4{
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 10 ; i++) {
NSLog(@"doing A :%d-%@",i,[NSThread currentThread]);
}
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 20 ; i++) {
NSLog(@"doing B :%d-%@",i,[NSThread currentThread]);
}
}];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//operation2 依赖于 operation1,operation1执行完才能执行operation2
[operation2 addDependency:operation1];
[queue addOperation:operation1];
[queue addOperation:operation2];
}