异步,同步,异步变同步
异步就是在另起一个线程执行任务,一般异步起动来之后,立马返回,当前线程继续往下走。多条线程
同步是在当前线程执行任务,等待同步启动并执行完之后,才返回,当前线程才可以继续往下走。一条线程
异步变同步, 也是新开启一个新线程去执行任务,但是等待异步起动并执行完之后,才继续往下走。多条线程
线程队列
线程队列,有一个线程一直在运行,在创建队列的时候就创建了很多个线程,持有那么多线程的句柄,通常维护着3个队列,总队列,忙队列,空闲队列。需要运行时,就从其中取出来一个执行。
串行队列,并行队列
串行队列异步运行,串行队列同步运行
并行队列异步运行,并行队列同步运行
串行Queue.async,调用一次queue.async, 就从queue的空闲队列中取线程,每次取出来的都是同一个线程,来执行任务, 执行完一个任务再执行另一个任务,始终在这个取出来的线程中运行
串行Queue.sync,是不会开启一个新线程的,就是在当前线程执行任务。在那个线程调的,就在那个线程上跑。
并行Queue.async,调用一次queue.async, 就从queue的从空闲队列中取线程,每次取出来的线程有可能相同,有可能不同, 来执行任务,只要空闲队列里有线程,就全部取出来,同时让他们干活。
并行Queue.sync,是不会开启一个新线程的,就是在当前线程执行任务。在那个线程调的,就在那个线程上跑。跟串行队列一样。
多线程:并行,并发
cpu调度执行时间片来区分。同时运行的就是并行,上下文切换的时间片运行是并发。我们说的多线程并发其实就是指并发和并行两种情况,不需要管具体的cpu是并行运行还是并发运行。
// 测试1, 每次取出来的thread都相同,因为是串行queue,一条一条执行
let t = DispatchQueue(label: "123")
for i in 0...10 {
print("开一个线程", i)
t.async {
sleep(5)
print(Thread.current, i)
}
}
print(Thread.current, "2")
// 测试2, 每次取出来的thread不一定相同,因为是并行queue,几乎同时打印
let t = DispatchQueue.global(qos: DispatchQoS.QoSClass.background)
for i in 0...10 {
print("开一个线程", i)
t.async {
sleep(5)
print(Thread.current, i)
}
}
print(Thread.current, "2")
// 测试3,取出来的thread不一样,因为queue不一样
for i in 0...10 {
print("开一个线程", i)
DispatchQueue(label: "123").async {
sleep(5)
print(Thread.current, i)
}
}
print(Thread.current, "2")
// 测试4,sync每次取出来的thread相同
let t = DispatchQueue(label: "123")
for i in 0...10 {
print("开一个线程", i)
t.sync {
sleep(5)
print(Thread.current, i)
}
}
print(Thread.current, "2")
总结: 深入理解某大神的一句话:
同步不开,异步开。串行开一条,并行开多条(具体多少条由任务的时间和队列的系统框架的线程池数量决定)。