iOS创建多线程的4种方式
- 1 pthread : C语言 只需了解,暂不介绍
- 2 NSThread :
- 3 GCD :
- 4 NSOperation :
特别注意:以下测试方法全部在主线程中调用
方式一:pthread创建方式
该方式暂不介绍
方式二:NSThread创建线程三种方法
- 对象方法
- 分类方法
- 类方法
对象方法
代码示例:
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(nslogThread) object:nil];
//注意启动一个线程并非就一定立即执行,而是处于就绪状态,当系统调度时才真正执行
[thread start];
- (void) nslogThread {
sleep(5);
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"callBack");
}
分类方法
特别注意:
另外performSelectorOnMainThread方法是NSObject的分类方法,每个NSObject对象都有此方法,
它调用的selector方法是当前调用控件的方法,例如使用UIImageView调用的时候selector就是UIImageView的方法
Object:代表调用方法的参数,不过只能传递一个参数(如果有多个参数请使用对象进行封装)
waitUntilDone:是否线程任务完成才往下边执行
//如果YES,则,阻塞当前线程,直至新开辟线程执行完毕,才往下执行
//如果NO,不阻塞当前线程
//在当前线程中执行(当前线程为主线程)
NSLog(@"before");
[self performSelectorOnMainThread:@selector(nslogThread) withObject:nil waitUntilDone:YES];
NSLog(@"after");
//创建新的线程
//[self performSelectorInBackground:@selector(nslogThread) withObject:nil];
//2016-05-26 13:04:28.595 NSThread三种方法[46373:1704985] <NSThread: 0x7fb9a2d2d040>{number = 2, name = (null)}
类方法
//分类方法
//selector:当前调用控件的方法,
//target:由哪一个对象执行该方法
//Object:代表调用方法的参数,不过只能传递一个参数(如果有多个参数请使用对象进行封装)
[NSThread detachNewThreadSelector:@selector(nslogThread) toTarget:self withObject:nil];
//2016-05-26 12:45:02.773 NSThread三种方法[45067:1693652] <NSThread: 0x7f92a0f0b250>{number = 2, name = (null)}
方式三:GCD创建线程
首先我们要弄明白GCD中的核心概念
核心概念:
-
任务
1 同步任务: 在当前线程中的任务,不会开启新的线程
2 异步任务:不在当前线程中的任务,会开启新的线程 -
队列
1 串行队列
2 并发队列
3 全局队列
4 主队列
串行队列
串行队列-同步任务
-(void)serialQueue_syn{
//1 任务
void (^task1)(void)=^(){
NSLog(@"task:%d,%@",1,[NSThread currentThread]);
};
void (^task2)(void)=^(){
NSLog(@"task:%d,%@",2,[NSThread currentThread]);
};
void (^task3)(void)=^(){
NSLog(@"task:%d,%@",3,[NSThread currentThread]);
};
//2 创建串行队列
//参数1:该队列的名字
//参数2:创建何种队列,如果DISPATCH_QUEUE_SERIAL则代表创建串行队列,其中#define DISPATCH_QUEUE_SERIAL NULL,即也可传入NULL
dispatch_queue_t serialQueue=dispatch_queue_create("serialQueue_syn", DISPATCH_QUEUE_SERIAL);
//3 向队列中添加同步任务
dispatch_sync(serialQueue, task1);
dispatch_sync(serialQueue, task2);
dispatch_sync(serialQueue, task3);
NSLog(@"serialQueue_over");
}
输出结果:
[1913:704162] task:1,<NSThread: 0x13d50c3e0>{number = 1, name = main}
[1913:704162] task:2,<NSThread: 0x13d50c3e0>{number = 1, name = main}
[1913:704162] task:3,<NSThread: 0x13d50c3e0>{number = 1, name = main}
[1913:704162] serialQueue_over
串行队列-异步任务
-(void)serialQueue_asyn{
void (^task1)(void)=^(){
NSLog(@"task:%d,%@",1,[NSThread currentThread]);
};
void (^task2)(void)=^(){
NSLog(@"task:%d,%@",2,[NSThread currentThread]);
};
void (^task3)(void)=^(){
NSLog(@"task:%d,%@",3,[NSThread currentThread]);
};
//创建串行队列
dispatch_queue_t serialQuere=dispatch_queue_create("serialQueue_asyn", NULL);
//向队列中添加异步任务
dispatch_async(serialQuere, task1);
dispatch_async(serialQuere, task2);
dispatch_async(serialQuere, task3);
NSLog(@"serialQueue_asyn");
}
输出结果:
[1916:704616] serialQueue_asyn
[1916:704631] task:1,<NSThread: 0x15fd6bde0>{number = 2, name = (null)}
[1916:704631] task:2,<NSThread: 0x15fd6bde0>{number = 2, name = (null)}
[1916:704631] task:3,<NSThread: 0x15fd6bde0>{number = 2, name = (null)}
** 串行队列总结:**
在串行队列中,同步任务则不创建新的线程,异步任务创建新的线程(只创建1条),对加入其中的任务,按照加入队列中的顺序执行,不改变任务的执行序列。
并发队列
并发队列-同步任务
-(void)concurrentQueue_syn{
void (^task1)(void)=^(){
NSLog( @"task:%d,%@",1,[NSThread currentThread]);
};
void (^task2)(void)=^(){
NSLog( @"task:%d,%@",2,[NSThread currentThread]);
};
void (^task3)(void)=^(){
NSLog( @"task:%d,%@",3,[NSThread currentThread]);
};
void (^task4)(void)=^(){
NSLog( @"task:%d,%@",4,[NSThread currentThread]);
};
void (^task5)(void)=^(){
NSLog( @"task:%d,%@",5,[NSThread currentThread]);
};
//2 创建并发队列
//参数1:队列名字
//参数2:创建队列类型:DISPATCH_QUEUE_CONCURRENT并发类型
dispatch_queue_t concurrentQueue=dispatch_queue_create("concurrentQueue_syn", DISPATCH_QUEUE_CONCURRENT);
//3 向队列中添加同步任务
dispatch_sync(concurrentQueue, task1);
dispatch_sync(concurrentQueue, task2);
dispatch_sync(concurrentQueue, task3);
dispatch_sync(concurrentQueue, task4);
dispatch_sync(concurrentQueue, task5);
NSLog(@"concurrent");
}
执行结果:
[1928:709535] task:1,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] task:2,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] task:3,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] task:4,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] task:5,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] concurrent
并发队列-异步任务
-(void) concurrentQueue_asyn{
void (^task1)(void)=^(){
NSLog( @"task:%d,%@",1,[NSThread currentThread]);
};
void (^task2)(void)=^(){
NSLog( @"task:%d,%@",2,[NSThread currentThread]);
};
void (^task3)(void)=^(){
NSLog( @"task:%d,%@",3,[NSThread currentThread]);
};
void (^task4)(void)=^(){
NSLog( @"task:%d,%@",4,[NSThread currentThread]);
};
void (^task5)(void)=^(){
NSLog( @"task:%d,%@",5,[NSThread currentThread]);
};
//创建并发队列
//参数1:队列名字
//参数2:创建队列类型:DISPATCH_QUEUE_CONCURRENT并发类型
dispatch_queue_t concurrentQueue=dispatch_queue_create("concurrentQueue_asyn", DISPATCH_QUEUE_CONCURRENT);
//向队列中添加异步任务
dispatch_async(concurrentQueue, task1);
dispatch_async(concurrentQueue, task2);
dispatch_async(concurrentQueue, task3);
dispatch_async(concurrentQueue, task4);
dispatch_async(concurrentQueue, task5);
NSLog(@"concurrent_asyn_over");
}
执行结果:
[1932:710530] concurrent_asyn_over
[1932:710569] task:4,<NSThread: 0x15ce76250>{number = 5, name = (null)}
[1932:710568] task:3,<NSThread: 0x15ce75c60>{number = 4, name = (null)}
[1932:710559] task:2,<NSThread: 0x15ce75b50>{number = 3, name = (null)}
[1932:710560] task:1,<NSThread: 0x15ce71900>{number = 2, name = (null)}
[1932:710570] task:5,<NSThread: 0x15ce773c0>{number = 6, name = (null)}
并发队列总结:
在并发队列中,同步任务不开辟线程,异步任务创建随机创建N条线程,并且任务执行顺序为无序状态
全局队列
全局队列-同步任务
-(void)globalQueue_async{
void (^task1)(void)=^(){
NSLog( @"task:%d,%@",1,[NSThread currentThread]);
};
void (^task2)(void)=^(){
NSLog( @"task:%d,%@",2,[NSThread currentThread]);
};
void (^task3)(void)=^(){
NSLog( @"task:%d,%@",3,[NSThread currentThread]);
};
void (^task4)(void)=^(){
NSLog( @"task:%d,%@",4,[NSThread currentThread]);
};
void (^task5)(void)=^(){
NSLog( @"task:%d,%@",5,[NSThread currentThread]);
};
//2 获得全局队列
dispatch_queue_t globalQueue=dispatch_get_global_queue(0, 0);
//3 向全局队列中添加异任务
dispatch_async(globalQueue, task1);
dispatch_async(globalQueue, task2);
dispatch_async(globalQueue, task3);
dispatch_async(globalQueue, task4);
dispatch_async(globalQueue, task5);
NSLog(@"globalQueue_async");
}
执行结果:
[1954:716253] task:1,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] task:2,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] task:3,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] task:4,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] task:5,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] globalQueue_sync
全局队列-异步任务
-(void)globalQueue_async{
void (^task1)(void)=^(){
NSLog( @"task:%d,%@",1,[NSThread currentThread]);
};
void (^task2)(void)=^(){
NSLog( @"task:%d,%@",2,[NSThread currentThread]);
};
void (^task3)(void)=^(){
NSLog( @"task:%d,%@",3,[NSThread currentThread]);
};
void (^task4)(void)=^(){
NSLog( @"task:%d,%@",4,[NSThread currentThread]);
};
void (^task5)(void)=^(){
NSLog( @"task:%d,%@",5,[NSThread currentThread]);
};
//2 获得全局队列
dispatch_queue_t globalQueue=dispatch_get_global_queue(0, 0);
//3 向全局队列中添加异任务
dispatch_async(globalQueue, task1);
dispatch_async(globalQueue, task2);
dispatch_async(globalQueue, task3);
dispatch_async(globalQueue, task4);
dispatch_async(globalQueue, task5);
NSLog(@"globalQueue_async");
}
执行结果:
[1958:716810] globalQueue_async
[1958:716924] task:3,<NSThread: 0x155dbc1c0>{number = 4, name = (null)}
[1958:716921] task:2,<NSThread: 0x155dbdae0>{number = 3, name = (null)}
[1958:716922] task:1,<NSThread: 0x155db9ba0>{number = 2, name = (null)}
[1958:716926] task:4,<NSThread: 0x155dbd3d0>{number = 5, name = (null)}
[1958:716928] task:5,<NSThread: 0x155dbbd70>{number = 6, name = (null)}
全局队列总结:
在全局队列中,同步任务不开辟线程,异步任务开辟N条随机线程,并且任务执行顺序为无序状态
主队列
主队列-同步任务
-(void)mainQueue_sync{
//创建任务
void (^task1)(void)=^(){
NSLog( @"task:%d,%@",1,[NSThread currentThread]);
};
void (^task2)(void)=^(){
NSLog( @"task:%d,%@",2,[NSThread currentThread]);
};
void (^task3)(void)=^(){
NSLog( @"task:%d,%@",3,[NSThread currentThread]);
};
void (^task4)(void)=^(){
NSLog( @"task:%d,%@",4,[NSThread currentThread]);
};
void (^task5)(void)=^(){
NSLog( @"task:%d,%@",5,[NSThread currentThread]);
};
//2 获取系统主队列
dispatch_queue_t mainQueue=dispatch_get_main_queue();
//3 向主队列中添加同步任务
dispatch_sync(mainQueue, task1);//在此处:一直在等带主线执行完毕,而主线程一直在等待该任务执行完毕
dispatch_sync(mainQueue, task2);
dispatch_sync(mainQueue, task3);
dispatch_sync(mainQueue, task4);
dispatch_sync(mainQueue, task5);
NSLog(@"mainQueue_sync");
}
输出结果:
什么也没有输出,因为:向主队列中添加同步任务会出现死等状态。
主队列-异步任务
-(void)mainQueue_async{
void (^task1)(void)=^(){
NSLog( @"task:%d,%@",1,[NSThread currentThread]);
};
void (^task2)(void)=^(){
NSLog( @"task:%d,%@",2,[NSThread currentThread]);
};
void (^task3)(void)=^(){
NSLog( @"task:%d,%@",3,[NSThread currentThread]);
};
void (^task4)(void)=^(){
NSLog( @"task:%d,%@",4,[NSThread currentThread]);
};
void (^task5)(void)=^(){
NSLog( @"task:%d,%@",5,[NSThread currentThread]);
};
//2 获取系统主队列
dispatch_queue_t mainQueue=dispatch_get_main_queue();
//3 向主对列中添加异步任务
dispatch_async(mainQueue, task1);
dispatch_async(mainQueue, task2);
dispatch_async(mainQueue, task3);
dispatch_async(mainQueue, task4);
dispatch_async(mainQueue, task5);
NSLog(@"mainQueue_async");
}
输出结果:
mainQueue_async
task:1,<NSThread: 0x134507960>{number = 1, name = main}
task:2,<NSThread: 0x134507960>{number = 1, name = main}
task:3,<NSThread: 0x134507960>{number = 1, name = main}
task:4,<NSThread: 0x134507960>{number = 1, name = main}
task:5,<NSThread: 0x134507960>{number = 1, name = main}
主队列总结:
在主队列中,同步任务会卡死主线程,异步任务不会创建线程,而是在主线程中执行。
方式四:NSOperation创建线程
核心概念:队列NSOperationQueue和任务NSOperation
队列NSOperationQueue分类:
- 主 队 列:由系统提供,通过[NSOperationQueue new]方式获取
- 并发队列:程序员创建[[NSOperationQueue alloc] init]方式获取
任务NSOperation分类:
- NSInvationOperation类型任务
- NSBlockOperation类型任务
主队列
操作主队列-NSInvationOperation类型任务
-(void)operationQueueAsynDemo1{
//1 获取主队列
NSOperationQueue *mainQueue=[NSOperationQueue mainQueue];
//1 创建invocation任务
NSInvocationOperation *invocationOper=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test:) object:@"mainQueue"];
//3 向对列中添加任务
[mainQueue addOperation:invocationOper];
}
-(void)test:(NSString *)info{
NSLog( @"%@--%@",info,[NSThread currentThread]);
}
输出结果:
主队列[2015:729865] mainQueue--<NSThread: 0x13750c370>{number = 1, name = main}
主队列-NSBlockOperation类型任务
-(void)operationQueueAsynDemo2{
//1 获取主队列
NSOperationQueue *mainQueue=[NSOperationQueue mainQueue];
//2 创建block任务
NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"-->%@",[NSThread currentThread]);
}];
//3 向队列中添加block任务
[mainQueue addOperation:blockOperation];
}
-(void)test:(NSString *)info{
NSLog( @"%@--%@",info,[NSThread currentThread]);
}
输出结果:
主队列[2018:730534] --><NSThread: 0x14d50c370>{number = 1, name = main}
添加block任务简略方式:
-(void)operationQueueAsynDemo2{
//1 获取主队列
NSOperationQueue *mainQueue=[NSOperationQueue mainQueue];
//2 创建block任务
NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"-->%@",[NSThread currentThread]);
}];
//3 向队列中添加block任务
[mainQueue addOperation:blockOperation];
}
** NSOperationQueue主队列总结:**
NSOperationQueue主队列不创建线程,并且异步方式执行,不然阻塞主线程。
并发队列
操作并发队列-NSInvationOperation类型任务
//并发队列 Invocation任务
-(void)operationQueueAsynDemo1 {
//1 创建队列:冲过alloc init方式创建的队列为并发异步队列
NSOperationQueue *concurrentQueue=[[NSOperationQueue alloc] init];
//2 创建任务
NSInvocationOperation *invocationOperation=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationOperationSyn:) object:@"OperationQueue_syn"];
//3 向队列中添加任务
[concurrentQueue addOperation:invocationOperation];
}
-(void)invocationOperationSyn:(NSString *)info{
NSLog(@"%@--%@",info,[NSThread currentThread]);
}
输出结果:
[2023:732400] --><NSThread: 0x134593e80>{number = 2, name = (null)}
并发队列-NSBlockOperation类型任务
//并发队列 block任务
-(void)operationQueueAsynDemo2{
//1 创建并发对列
NSOperationQueue *concurrentQueue=[[NSOperationQueue alloc] init];
//2 创建block任务
NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
NSLog( @"%@-->",[NSThread currentThread]);
}];
//3 向队列中添加任务
[concurrentQueue addOperation:blockOperation];
}
-(void)invocationOperationSyn:(NSString *)info{
NSLog(@"%@--%@",info,[NSThread currentThread]);
}
输出结果:
[2026:733095] <NSThread: 0x15cd9aac0>{number = 2, name = (null)}-->
添加block任务简略方式:
-(void ) operationQueueAsynDemo3{
//1 创建并发队列
NSOperationQueue *concurrent=[[NSOperationQueue alloc] init];
//2 向队里中添加 blok
[concurrent addOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
}
** NSOperationQueue并发队列总结:**
NSOperationQueue并发队列创建线程,并且异步方式执行