转载请注明出处:http://www.jianshu.com/p/ffd1f7a5db20
作者:纪小衰
参考资料:http://www.cocoachina.com/ios/20160804/17291.html
同步:多个任务情况下,一个任务A执行结束,才可以执行另一个任务B。只存在一个线程也就是主线程。 异步:多个任务情况下,一个任务A正在执行,同时可以执行另一个任务B。任务B不用等待任务A结束才执行。
并行:指两个或多个时间在同一时刻发生。多核CUP同时开启多条线程供多个任务同时执行,互不干扰。 并发:指两个或多个事件在同一时间间隔内发生。可以在某条线程和其他线程之间反复多次进行上下文切换,看上去就好像一个CPU能够并且执行多个线程一样。其实是伪异步。
多线程编程会导致的问题:
1.数据竞争
2.死锁
3.内存消耗和线程切换cpu消耗
使用多线程的必要性: 主线程中会描绘用户界面和处理触摸事件,如果在主线程中进行长事件处理会导致主线程阻塞,妨碍主线程的RunLoop主循环的执行
GCD的使用: 苹果官方对GCD是这样说明的:开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。Dispatch Queue是按照追加的顺序 进行处理,先进先出FIFO。
Serial Dispatch Queue串行调度队列:等待现在执行中的事件处理结束再执行下一个任务。多个串行队列可以并发执行,但是创建多个线程的消耗会比较大,此时考虑使用并行队列
Concurrent Dispatch Queue并发调度队列:不等待现在执行中的事件处理结束就可以开始下一个任务
//创建串行队列
dispatch_queue_t queue1 = dispatch_queue_create("com.jr1", DISPATCH_QUEUE_SERIAL);
//创建并行队列
dispatch_queue_t queue2 = dispatch_queue_create("com.jr1", DISPATCH_QUEUE_CONCURRENT);
//获取系统的主队列 (Main Dispatch Queue是在主线程中执行的Dispatch Queue,也就是Serial Dispatch Queue)
dispatch_queue_t queue3 = dispatch_get_main_queue();
//获取全局队列 (param:优先级,保留字段 type:concurrent)
dispatch_queue_t queue4 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t queue5 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t queue6 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_queue_t queue7 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
//重新设置队列的优先级
dispatch_queue_t newBackQueue = dispatch_queue_create("backQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t backGroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(newBackQueue, backGroundQueue);
//程序执行过程中只执行一次的队列
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
});
//延迟执行 延迟执行指在多长时间以后追加到队列中,而不是执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
//3.1串行队列同步执行 输出:1 2 3
dispatch_queue_t q1 = dispatch_queue_create("com.jr1", DISPATCH_QUEUE_SERIAL);
dispatch_async(q1, ^{
sleep(1);
NSLog(@"SERIA_ASYNC_1");
});
dispatch_async(q1, ^{
sleep(0.5);
NSLog(@"SERIA_ASYNC_2");
});
dispatch_async(q1, ^{
sleep(0.2);
NSLog(@"SERIA_ASYNC_3");
});
//3.2串行队列同步执行 输出 :1 2 3
dispatch_queue_t q2 = dispatch_queue_create("com.jr2", DISPATCH_QUEUE_SERIAL);
dispatch_sync(q2, ^{
sleep(1);
NSLog(@"SERIAL_SYNC_1");
});
dispatch_sync(q2, ^{
sleep(0.5);
NSLog(@"SERIAL_SYNC_2");
});
dispatch_sync(q2, ^{
sleep(2);
NSLog(@"SERIAL_SYNC_3");
});
//3.3并行队列异步执行 输出 2 1 4 3
dispatch_queue_t q3 = dispatch_queue_create("com.jr3", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(q3, ^{
sleep(1);
NSLog(@"CONCURRENT1");
});
dispatch_async(q3, ^{
sleep(0.4);
NSLog(@"CONCURRENT2");
});
dispatch_async(q3, ^{
sleep(3);
NSLog(@"CONCURRENT3");
});
dispatch_async(q3, ^{
sleep(2);
NSLog(@"CONCURRENT4");
});
//队列组test1 同步任务1 同步任务超时 同步任务2 同步任务完成
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, globalQueue, ^{
sleep(1);
NSLog(@"同步任务1");
});
dispatch_group_async(group, globalQueue, ^{
sleep(4);
NSLog(@"同步任务2");
});
dispatch_group_notify(group, globalQueue, ^{
NSLog(@"同步任务完成");
});
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);;
long result = dispatch_group_wait(group, time);
if (result == 0) {
NSLog(@"任务全部执行完毕");
}else{
NSLog(@"同步任务超时");
}
//队列组test2 异步任务2 异步任务1 任务结束
dispatch_group_t group2 = dispatch_group_create();
dispatch_queue_t groupQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group2, groupQueue2, ^{
dispatch_group_enter(group2);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"异步任务1");
dispatch_group_leave(group2);
});
});
dispatch_group_async(group2, groupQueue2, ^{
dispatch_group_enter(group2);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"异步任务2");
dispatch_group_leave(group2);
});
});
dispatch_group_notify(group2, groupQueue2, ^{
NSLog(@"任务结束");
});
//异步的任务不能使用dispatch_group_wait,因为在闭包中的任务同步部分执行完后任务就结束了,但是dispatch_group_leave还没有调用,所以一定返回任务没有执行成功
dispatch_time_t time2 = dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC);
long result2 = dispatch_group_wait(group2, time2);
if (result2==0) {
NSLog(@"异步任务成功");
}else{
NSLog(@"异步任务失败");
}
//提交多个任务 可以实现对于数据的元素并发循环(dispatch_apply为同步返回,阻塞当前线程直到所有的任务结束,如果加入到串行队列,则所有的任务串行执行,如果是并行队列,则所有的任务并发执行。使用并行队列,begin和end不一定成对,数字也不是按照顺序输出,如果使用串行队列,begin和end成对输出,并且数字按照顺序输出)
dispatch_queue_t applyQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t applyQueue2 = dispatch_queue_create("applyQueue", DISPATCH_QUEUE_SERIAL);
dispatch_apply(10, applyQueue2, ^(size_t index) {
NSLog(@"indexBegin:%ld",index);
sleep(0.3 * (10 - index));
NSLog(@"%ld",index);
NSLog(@"indexEnd:%ld",index);
});
NSLog(@"Apply done");
//队列阻塞 (可解决读者写者的问题)
dispatch_queue_t dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(dbQueue, ^{
NSLog(@"正在读取1");
sleep(1);
NSLog(@"结束读取1");
});
dispatch_async(dbQueue, ^{
NSLog(@"正在读取2");
sleep(0.5);
NSLog(@"结束读取2");
});
dispatch_barrier_sync(dbQueue, ^{
NSLog(@"正在写入");
sleep(5);
NSLog(@"结束写入");
});
dispatch_async(dbQueue, ^{
NSLog(@"正在读取3");
sleep(0.5);
NSLog(@"结束读取3");
});
//队列挂起与恢复
dispatch_queue_t someQueue = dispatch_queue_create("testQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_suspend(someQueue);
dispatch_resume(someQueue);