iOS中实现多线程的技术很多,但我钟爱GCD,原因如下:
1. 使用简单;
2. 效率高;
3. 苹果推荐;
工作原理:往dispatch queue里添加要执行的任务,由queue管理任务的执行。
dispatch queue有两种:serial queue(串行)和concurrent queue(并行) ;
serial queue(串行)
特点:queue中任何一个任务的执行,必须等到上个任务执行完毕,即A任务开始执行后需要等到执行结束后B任务便可开始执行。
使用serial queue有两种方式:获得mainQueue、创建serial queue。
1.获得mainQueue
//获取mainQueue
dispatch_queue_t mainQueue =dispatch_get_main_queue();
//打印测试
dispatch_async(mainQueue, ^{
NSLog(@"任务1,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});//在block里写要执行的任务(代码)
dispatch_async(mainQueue, ^{
NSLog(@"任务2,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(mainQueue, ^{
NSLog(@"任务3,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
注:number为线程编号,1为主线程,其它均为子线程。
看打印结果便可知,使用mainQueue,所有的任务都会在主线程中按顺序执行,执行完一个才会执行下一个。
2.创建serial queue
//创建mySerialQueue
dispatch_queue_t mySerialQueue =dispatch_queue_create("com.xiaolan.GCD.mySerialQueue",DISPATCH_QUEUE_SERIAL);//苹果推荐使用反向域名格式。
dispatch_async(mySerialQueue, ^{
NSLog(@"任务1,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});//在block里写要执行的任务(代码)
dispatch_async(mySerialQueue, ^{
NSLog(@"任务2,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(mySerialQueue, ^{
NSLog(@"任务3,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
注:number为线程编号,1为主线程,其它均为子线程。
看打印结果便可知,使用自创建的serial queue,所有的任务都会在子线程中按顺序执行,执行完一个才会执行下一个。
concurrent queue(并行)
特点:queue中所有的任务按顺序执行,不需要等上一个任务执行完毕便可开始执行下一个任务,即A任务开始执行后不需要等到执行结束,B任务便可开始执行。
使用serial queue有两种方式:获得global queue、创建concurrent queue。
1.获得global queue
dispatch_queue_t globalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
//第一个参数控制globalQueue的优先级,一共有4个优先级DISPATCH_QUEUE_PRIORITY_HIGH、DISPATCH_QUEUE_PRIORITY_DEFAULT、DISPATCH_QUEUE_PRIORITY_LOW、DISPATCH_QUEUE_PRIORITY_BACKGROUND。
第二个参数是苹果预留参数,未来会用,目前填写为0.
dispatch_async(globalQueue, ^{
NSLog(@"任务1,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});//在block里写要执行的任务(代码)
dispatch_async(globalQueue, ^{
NSLog(@"任务2,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(globalQueue, ^{
NSLog(@"任务3,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(globalQueue, ^{
NSLog(@"任务4,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(globalQueue, ^{
NSLog(@"任务5,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(globalQueue, ^{
NSLog(@"任务6,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
注:number为线程编号,1为主线程,其它均为子线程。
根据打印结果暂时可以有以下几点疑虑:
为什么没有主线程参与;
即使从子线程开始6个任务为什么之开辟了5个子线程。
先不要着急,看完自创建的concurrent queue后我们进行总结。
2.创建concurrent queue
//创建myConcurrentQueue
dispatch_queue_t myConcurrentQueue =dispatch_queue_create("com.xiaolan.GCD.myConcurrentQueue",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(myConcurrentQueue, ^{
NSLog(@"任务1,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});//在block里写要执行的任务(代码)
dispatch_async(myConcurrentQueue, ^{
NSLog(@"任务2,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(myConcurrentQueue, ^{
NSLog(@"任务3,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(myConcurrentQueue, ^{
NSLog(@"任务4,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(myConcurrentQueue, ^{
NSLog(@"任务5,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
dispatch_async(myConcurrentQueue, ^{
NSLog(@"任务6,线程%@,是否是主线程:%d",[NSThreadcurrentThread],[[NSThreadcurrentThread] isMainThread]);
});
注:number为线程编号,1为主线程,其它均为子线程。
看到这个打印结果有意思吧,记下来我们就可以总结了:
1. concurrent queue 中所有的任务都在子线程中执行;
2. 开始较晚的任务未必最后结束,开始较早的任务未必最先完成;
3. 开辟的线程数量不一定等于任务的数量,取决于多方面因素,比如:任务的数量,系统的内存资源等等,会以最优的方式开辟线程—根据需要开辟适当的线程。