GCD
- 全局并发队列
DispatchQueue.global().async {
print("当前线程:\(Thread.current)")
}
- 拿到主队列(主线程)
DispatchQueue.main.async {
print("回到主线程刷新UI")
}
异步任务
1.回到主线程
- 方式一
let item = DispatchWorkItem {
print("子线程:",Thread.current)
DispatchQueue.main.async {
print("主线程:\(Thread.current)")
}
}
DispatchQueue.global().async(execute: item)
- 方式二:notify
let item = DispatchWorkItem {
print("子线程:",Thread.current)
}
DispatchQueue.global().async(execute: item)
//回到主队列
item.notify(queue: DispatchQueue.main) {
print("主线程:\(Thread.current)")
}
2.对上的功能进行封装
import Foundation
struct Asyncs {
public typealias Task = () -> Void
public static func async(_ task: @escaping Task) {
//传入全局任务
_async(task)
}
public static func async(_ task: @escaping Task, _ mainTask: @escaping Task) {
//传入全局任务,主队列任务
_async(task, mainTask)
}
private static func _async(_ task: @escaping Task, _ mainTask: Task? = nil) {
let item = DispatchWorkItem(block: task)
DispatchQueue.global().async(execute: item)
//可选项绑定
if let main = mainTask {
//item⾥⾯的任务完成之后,再到主队列执⾏
item.notify(queue: DispatchQueue.main, execute: main)
}
}
}
- 在子线程处理
Asyncs.async {
print("子线程:",Thread.current)
}
- 在子线程操作完后想回到主线程
Asyncs.async {
print("子线程:",Thread.current)
} _: {
print("在主线程:",Thread.current)
}
main主线程延迟
- 在主线程延迟
let time = DispatchTime.now() + 3
DispatchQueue.main.asyncAfter(deadline: time) {
print("在主线程延迟3秒")
}
- 在子线程延迟
let time = DispatchTime.now() + 3
DispatchQueue.global().asyncAfter(deadline: time) {
print("在子线程延迟3秒")
}
- 对延迟封装
/// 延迟
/// - Parameters:
/// - seconds: 延迟时间(秒)
/// - block: 延迟的任务
/// - Returns: item
@discardableResult //没⽤到返回值可以忽略,不会有警告
public static func delay(_ seconds: Double, _ block: @escaping Task) -> DispatchWorkItem {
let item = DispatchWorkItem(block: block)
//在主线程延迟
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds, execute: item)
return item
}
Asyncs.delay(3) {
print("----在主线程延迟3秒----")
}
异步延迟
@discardableResult
public static func asyncDelay(_ seconds: Double, _ task: @escaping Task) -> DispatchWorkItem {
return _asyncDelay(seconds, task)
}
@discardableResult
public static func asyncDelay(_ seconds: Double, _ task: @escaping Task, _ mainTask: @escaping Task) -> DispatchWorkItem {
return _asyncDelay(seconds, task, mainTask)
}
private static func _asyncDelay(_ seconds: Double, _ task: @escaping Task, _ mainTask: Task? = nil) -> DispatchWorkItem {
let item = DispatchWorkItem(block: task)
//异步延迟
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + seconds, execute: item)
if let main = mainTask {
item.notify(queue: DispatchQueue.main, execute: main)
}
//为什么要返回item?
//因为是延迟执⾏,⽐如3秒,如果在2秒的时候想要取消任务,就拿到item取消:item?.cancel()
return item
}
- 使用
Asyncs.asyncDelay(3.0) {
print("延迟任务...")
}
private var item: DispatchWorkItem?
item = Asyncs.asyncDelay(5.0) {
print("延迟任务...")
} _: {
print("延迟任务执行完回到主队列")
}
- 取消任务
item?.cancel()
once
- dispatch_once在Swift中已被废弃,取而代之
- 可使用类型属性
- 全局变量、常量
- 默认自带lazy + dispatch_once效果
下面几种方式,在调用的时候只会执行1次。
import UIKit
fileprivate var initTask: Void = {
print("initTask")
}()
class ViewController: UIViewController {
static var age: Int = {
print("age")
return 0
}()
static var sex: Int = getSex()
static func getSex()->Int {
print("getSex")
return 0
}
static var weight: Void = {
print("weight")
}()
override func viewDidLoad() {
super.viewDidLoad()
print(Self.age)
print(Self.sex)
let _ = Self.weight
let _ = initTask
}
}
加锁
GCD 信号量(DispatchSemaphore)
class Cache {
private static var data = [String: Any]()
//数字写⼏,表示同时有多少条线程访问他,⼀般写1
private static var lock = DispatchSemaphore(value: 1)
static func set(_ key: String, _ value: Any) {
lock.wait() //加锁
defer {
lock.signal()//解锁
}
data[key] = value
}
}
Foundation框架中的锁
- NSLock()
这种会产⽣死锁,⽐如set⾥⾯⼜调⽤set
class Cache {
private static var data = [String: Any]()
private static var lock = NSLock()
static func set(_ key: String, _ value: Any) {
lock.lock() //加锁
defer {
lock.unlock()//解锁
}
data[key] = value
}
}
- NSRecursiveLock()
使⽤递归锁,不会产⽣死锁
class Cache {
private static var data = [String: Any]()
private static var lock = NSRecursiveLock()
static func set(_ key: String, _ value: Any) {
lock.lock() //加锁
defer {
lock.unlock()//解锁
}
data[key] = value
}
}