建筑效果图网站有哪些,哪些网站做渣土车租恁,用html5做网站的优点,房地产网站怎么推广iOS 常用有三种线程管理方式#xff0c;分别是 NSThread、GCD 与 NSOperation#xff0c;现在我们先来了解一下其中的 GCD
串行与并行针对的是任务队列#xff0c;而同步与异步#xff0c;针对的则是线程。
Serial Queue Sync 序列执行同步
Serial Queue Async 序列执…iOS 常用有三种线程管理方式分别是 NSThread、GCD 与 NSOperation现在我们先来了解一下其中的 GCD
串行与并行针对的是任务队列而同步与异步针对的则是线程。
Serial Queue Sync 序列执行同步
Serial Queue Async 序列执行 异步 按顺序
Concurrent Queue Sync 并发 同步 按顺序
Concurrent Queue Async 并发 异步 真正多线程不按顺序
自定义串行队列有能力启动主线程和后台线程只能启动一个后台线程不会发生死锁。同步任务会自动安排在主线程执行遇到异步任务自动安排在后台线程执行所以不会死锁。
DispatchWorkItem 可添加 item 到队列中
//1. 只带尾随闭包
let item1 DispatchWorkItem {print(item1)
}//2. 指定qos执行优先级或flags特殊行为标记
let item2 DispatchWorkItem(qos: .userInteractive, flags: .barrier) {print(item2)
}DispatchQueue Main queue (串行队列) 仅能运行在主线程上 let mainQueue DispatchQueue.mainGlobal queue并行队列 Concurrent let globalQueue DispatchQueue.global()Custom queue默认串行 //串行队列label名字随便取
let serialQueue DispatchQueue(label: test)//并行队列
let concurrentQueue DispatchQueue(label: test, attributes: .concurrent)添加任务
异步
let mainQueue DispatchQueue.main
mainQueue.async(execute: item1)let globalQueue DispatchQueue.global()
globalQueue.async(execute: item1)let serialQueue DispatchQueue(label: serial)
serialQueue.async(execute: item1)let concurrentQueue DispatchQueue(label: concurrent, attributes: .concurrent)
concurrentQueue.async(execute: item1)同步
let mainQueue DispatchQueue.main
mainQueue.sync(execute: item1) // 必定引起死锁let globalQueue DispatchQueue.global()
globalQueue.sync(execute: item1)let serialQueue DispatchQueue(label: serial)
serialQueue.sync(execute: item1)let concurrentQueue DispatchQueue(label: concurrent, attributes: .concurrent)
concurrentQueue.sync(execute: item1)队列死锁而不是线程死锁。主队列添加同步任务造成死锁的根本原因
主队列只能运行在主线程。主队列没有本事开启后台线程去干别的事情。主队列一旦混入同步任务就会跟已经存在的异步任务相互等待导致死锁。
DispatchGroup
可把多个任务放到 group方便管理。
当组内所有任务执行完成GCD API 发送相应的通知。
notify(): 不阻塞当前线程wait()阻塞当前线程
自定义串行队列一个异步或同步任务A嵌套另一个同步任务B会引起死锁。
A、B任务等效为A1 - B - A2。
// 当前任务
let queue DispatchQueue.init(label: name)
queue.sync {// 死锁。同步要等外层执行后这里才能执行而外层的执行需要这里先执行完。queue.sync {print(Thread.current) // 同步任务} // 当前任务print(Thread.current)
}并行队列添加同步任务不会死锁因为同步任务被安排在主线程执行异步任务被安排在后台线程执行。
所有的同步任务最终都要安排到主线程运行主线程运行长耗时任务会导致界面严重卡顿。
// 这两种方式都会使界面卡顿15s
override func viewDidAppear(_ animated: Bool) {//1. 全局队列执行同步任务DispatchQueue.global().sync {sleep(15)//当前线程休眠15秒}//2. 主队列执行异步任务DispatchQueue.main.async {sleep(15)//当前线程休眠15秒}
}GCD 正确做法A、B都定义成异步任务在并行队列中嵌套异步任务最后切换到主队列去刷新UI let queue DispatchQueue(label: com.apple.request, attributes: .concurrent)//异步执行
queue.async {print(开始请求数据 \(Date()) thread: \(Thread.current))sleep(10)//模拟网络请求print(数据请求完成 \(Date()) thread: \(Thread.current))//异步执行queue.async {print(开始处理数据 \(Date()) thread: \(Thread.current))sleep(5)//模拟数据处理print(数据处理完成 \(Date()) thread: \(Thread.current))//切换到主队列刷新UIDispatchQueue.main.async {print(UI刷新成功 \(Date()) thread: \(Thread.current))}}
}
DispatchQueue.main 自动生成的主队列对象可获取
DispatchQueue.global
DispatchQueue() 默认是序列队列
DispatchQueue(.concurrent) 并发队列
同步任务都会被分配到主线程。
global、自定义 serial 队列、并发队列都有能力把异步任务分配到子线程。serial 只能开启一个子线程做并发任务足够了。
同队列中同步任务会等待前方任务执行完再执行。先来先服务
number 是队列标识name 是线程标识使用 serial 安排同步任务和异步任务会将同步的分给主线程把异步的分给后台某个匿名线程。
let queue DispatchQueue.init(label: hei)
queue.async { print(Thread.current)
}queue.sync {queue.async {print(Thread.current) } // 虽然比下面的 print 早但是把这个异步任务发到另外线程这个过程需要时间。print(Thread.current)
}queue.async { print(Thread.current)
} queue.sync {print(Thread.current)
}// 结果
// NSThread: 0x7fde7c806950{number 5, name (null)}
// _NSMainThread: 0x7fde7cb06570{number 1, name main}
// NSThread: 0x7fde7c806950{number 5, name (null)}
// NSThread: 0x7fde7c806950{number 5, name (null)}
// _NSMainThread: 0x7fde7cb06570{number 1, name main}如果 serial 队列嵌套同步任务将会死锁。
// 当前任务
let queue DispatchQueue.init(label: name)
queue.sync {// 死锁。同步要等外层执行后这里才能执行而外层的执行需要这里先执行完。queue.sync {print(Thread.current) // 同步任务} // 当前任务print(Thread.current)
}