多线程中的队列有:
串行队列,并发队列,全局队列(并发),主队列(串行)。
执行的方法有:同步执行和异步执行。
提到多线程:pthread,NSThread,GCD,NSOperation
其中phtread是跨平台的。
GCD和NSOperation都是常用的,后者是基于前者的。
两者区别:
GCD的核心概念是将一个任务添加到队列,指定任务执行的方法,然后执行。
NSOperation则是直接将一个操作添加到队列中。
/创建串行队列
dispatch_queue_t testqueue = dispatch_queue_create("queue2017", NULL);
// 执行任务
for (int i = 0; i<10; i++)
{
dispatch_sync(testqueue, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"串行队列 同步执行");
执行结果可以看到全在主线程执行,并且是按照数序执行,循环结束之后主线程的打印才输出。
//创建串行队列
dispatch_queue_t testqueue = dispatch_queue_create("queue2017", NULL);
// 执行任务
for (int i = 0; i<10; i++)
{
dispatch_async(testqueue, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"串行队列 异步执行");
结果显示,系统开了1条异步线程,因此全部在线程3执行,并且是顺序执行。主线程打印虽然在最上面,但是这个先后顺序是不确定,有可能会混在中间。
//创建并发队列
dispatch_queue_t testqueue = dispatch_queue_create("queue2017", DISPATCH_QUEUE_CONCURRENT);
// 执行任务
for (int i = 0; i<10; i++)
{
dispatch_sync(testqueue, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"并发队列 同步执行");
运行结果:
这个运行结果和第1种的(串行队列,同步执行)是一模一样的。
因为同步任务的概念就是按顺序执行,后面都要等。言外之意就是不允许多开线程。所以一旦是同步执行,前面什么队列已经没区别了。
//创建并发队列
dispatch_queue_t testqueue = dispatch_queue_create("queue2017", DISPATCH_QUEUE_CONCURRENT);
// 执行任务
for (int i = 0; i<10; i++)
{
dispatch_async(testqueue, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"并发队列 异步执行");
系统开了多条线程,并且执行的顺序也是乱序的
NSLog(@"之前 - %@", [NSThread currentThread]);
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"sync - %@", [NSThread currentThread]);
});
NSLog(@"之后 - %@", [NSThread currentThread]);
运行结果为卡死
卡死的原因是循环等待,主队列的东西要等主线程执行完,而因为是同步执行不能开线程,所以下面的任务要等上面的任务执行完,所以卡死。
// 主队列 - 程序启动之后已经存在主线程,主队列同样存在
dispatch_queue_t q = dispatch_get_main_queue();
// 安排一个任务
for (int i = 0; i<10; i++)
{
dispatch_async(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"sleep");
[NSThread sleepForTimeInterval:2.0];
NSLog(@"主队列,异步执行");
主线程在睡会之后才打印,循环一直在等着。因为主队列的任务虽然会加到主线程中执行,但是如果主线程里也有任务就必须等主线程任务执行完才轮到主队列的。
dispatch_queue_t q = dispatch_queue_create("queue2017", DISPATCH_QUEUE_CONCURRENT);
// 1. 用户登录,必须要第一个执行
dispatch_sync(q, ^{
[NSThread sleepForTimeInterval:2.0];
NSLog(@"用户登录 %@", [NSThread currentThread]);
});
// 2. 扣费
dispatch_async(q, ^{
NSLog(@"扣费 %@", [NSThread currentThread]);
});
// 3. 下载
dispatch_async(q, ^{
NSLog(@"下载 %@", [NSThread currentThread]);
});
NSLog(@"同步任务的使用");
“用户登陆”在主线程打印,后两个在异步线程打印。
上面的“用户登陆”使用同步执行,后面的扣费和下载都是异步执行。所以“用户登陆”必须第一个打印出来不管等多久,然后后面的两个异步和主线程打印会不确定顺序的打印。这就是日常开发中,那些后面对其有依赖的必须要先执行的任务使用同步执行,然后反正都要执行先后顺序无所谓的使用异步执行。
dispatch_queue_t queue = dispatch_queue_create("queue2017", DISPATCH_QUEUE_CONCURRENT);
void (^task)() = ^ {
// 1. 用户登录,必须要第一个执行
dispatch_sync(queue, ^{
NSLog(@"用户登录 %@", [NSThread currentThread]);
});
// 2. 扣费
dispatch_async(queue, ^{
NSLog(@"扣费 %@", [NSThread currentThread]);
});
// 3. 下载
dispatch_async(queue, ^{
NSLog(@"下载 %@", [NSThread currentThread]);
});
};
dispatch_async(queue, task);
[NSThread sleepForTimeInterval:1.0];
NSLog(@"block异步任务包裹同步任务");
因为整个block是在异步执行的,所以即使里面“用户登陆”是同步执行,那也无法在主线程中执行,只能开一条异步线程执行,因为是同步的所以必须等他先执行,后面的“扣费”和“下载”在上面同步执行结束之后,不确定顺序的打印。
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 10; i++)
{
dispatch_async(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
[NSThread sleepForTimeInterval:1.0];
NSLog(@"全局队列");
全局队列的本质就是并发队列,只是在后面加入了,“服务质量”,和“调度优先级” 两个参数,这两个参数一般为了系统间的适配,最好直接填0和0。