三种线程操作
Thread: 最轻,灵活度高,可以取消。但是只能有一个传参。
Operation: 操作对象+队列,可以取消,可以自己控制操作对象何时结束。
Grand Central Dispatch: 调度对象,操作对象, 目前没有找到取消方法。
Thread
官方文档Thread 最轻,灵活度最高
- 方法1,使用实例方法直接创建主线程并调用执行。
- 方法2,创建新线程,调用 start() 或 main() 方法执行线程。
- start(), 在新建的线程中运行方法。
- main(), 调用 routine 使方法在主线程中运行。
- cancel(), 将线程状态置为取消状态
- 测试代码
import UIKit
class Test {
func start() {
/// 方法1: 使用类方法创建线程并直接运行
Thread.detachNewThreadSelector(#selector(startAction), toTarget: self, with: nil)
//方式2:使用构造器方法创建线程,最后使用 main() 或者start() 启动线程使用
let myThread = Thread(target: self,
selector: #selector(startAction),
object: nil)
myThread.start()
myThread.main()
}
//定义一个下载图片的方法,线程调用
@objc private func startAction(){
print("执行了线程:\(Thread.current)")
}
}
let myClass = Test()
DispatchQueue.main.async {
myClass.start()
}
Operation
- Test0: 同一队列(OperationQueue)的不同操作对象(Operation)可能会在不同的线程执行;如果添加队列依赖则可以保证在统一线程中运行。
- Test1: 可自己创建 Operation,在 main() 中写自己需要执行的代码。
- 可以将加入队列的的对象调用方法个
operation1.cancel()
取消执行。- Objective-C 可以重载 Operation 中的方法自己控制对象何时运行结束, 关键代码如下
queue.maxConcurrentOperationCount = 1
self.willChangeValue(for: \ActionOperation.isFinished)
self.willfinish = true
self.didChangeValue(for: \ActionOperation.isFinished)
- 测试代码
import UIKit
class Test0 {
func start() {
let operation0 = BlockOperation(block: {
print("队列-0, 执行了, \(Thread.current)")
})
let operation1 = BlockOperation(block: {
print("队列-1, 执行了, \(Thread.current)")
})
//创建一个NSOperationQueue实例并添加operation
let queue = OperationQueue()
print("准备运行队列-0")
queue.addOperation(operation0)
print("准备运行队列-1")
queue.addOperation(operation1)
// operation1.cancel()
}
}
class Test1 {
func start() {
/// 创建线程对象
let actionOperation = ActionOperation()
let nextOperation = BlockOperation {
print("finish!!!")
}
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
queue.addOperation(actionOperation)
queue.addOperation(nextOperation)
}
}
class ActionOperation: Operation {
private var willfinish: Bool = false
override func main(){
print("对象执行了\(Thread.current)")
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
print("我真的执行结束了")
self.willChangeValue(for: \ActionOperation.isFinished)
self.willfinish = true
self.didChangeValue(for: \ActionOperation.isFinished)
}
print("只是方法完毕!!!")
}
override var isFinished: Bool {
print("----\(ffffinish)")
return ffffinish
}
}
let test0 = Test0()
DispatchQueue.main.async {
test0.start()
}
let test1 = Test1()
DispatchQueue.main.async {
test1.start()
}
GCD Group
let queue = DispatchQueue(label: "current", qos: DispatchQoS.userInteractive, attributes: .concurrent)
let gcdGroup = DispatchGroup()
gcdGroup.enter()
queue.async {
print("first")
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
print("first_after")
gcdGroup.leave()
}
}
gcdGroup.enter()
queue.async {
print("second")
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
print("second_after")
gcdGroup.leave()
}
}
gcdGroup.notify(queue: queue) {
print("finish")
}
//second
//first
//second_after
//first_after
//finish
Grand Central Dispatch
GCD 获取各种队列的方法
创建串行队列
let serial = DispatchQueue(label: "serialQueue1")
//创建并行队列
let concurrent = DispatchQueue(label: "concurrentQueue1", attributes: .concurrent)
//获取全局队列
let globalQueue = DispatchQueue.global(qos: .default)
//获取主线程队列
let mainQueue = DispatchQueue.main
- 全局队列
- DispatchQueue.global…sync { Code } 同步当前线程执行代码块, Code 代码块中的代码执行完毕后,才会继续执行下面方法, 不会造成亨死锁。
- DispatchQueue.global…async 重新开启线程,执行代码块。
//async异步追加Block块(async函数不做任何等待)
DispatchQueue.global(qos: .default).async {
//处理耗时操作的代码块...
print("do work: \(Thread.current)")
//操作完成,调用主线程来刷新界面
DispatchQueue.main.async {
print("main refresh: \(Thread.current)")
}
}
//添加同步代码块到global队列
//不会造成死锁,但会一直等待代码块执行完毕
print("当前的线程:\(Thread.current)")
serial.async {
DispatchQueue.global(qos: .default).sync {
print("sync1: \(Thread.current)")
sleep(3)
}
print("end")
}
- 一下代码慎用,如果执行环境为主线程,会造成死锁。
DispatchQueue.main.sync {
print("sync2")
}
GCD 操作对象
- 串行异步、同步队列保证在同一线程中顺序执行。
- DispatchWorkItem 非 open 类,不能继承创建子类
let workItem0 = DispatchWorkItem {
print("workItem0::\(Thread.current)")
}
let workItem1 = DispatchWorkItem {
print("workItem1::\(Thread.current)")
}
创建串行队列
let serial = DispatchQueue(label: "serialQueue1")
serial.async(execute: workItem0)
serial.async(execute: workItem1)
//serial.sync(execute: workItem0)
//serial.sync(execute: workItem1)
- 并行同步队列,保证在同一线程中运行,运行顺序确定。
- 并行异步队列,不能保证在同一线程中运行,运行顺序不确定。
let workItem0 = DispatchWorkItem {
print("workItem0::\(Thread.current)")
sleep(0)
}
let workItem1 = DispatchWorkItem {
print("workItem1::\(Thread.current)")
}
//创建并行队列
let concurrent = DispatchQueue(label: "concurrentQueue1", attributes: .concurrent)
DispatchQueue.global().async {
concurrent.async(execute: workItem0)
concurrent.async(execute: workItem1)
//concurrent.sync(execute: workItem0)
//concurrent.sync(execute: workItem1)
}