Swift 线程使用

如果感觉不错谢谢点赞。
如有问题请写评论,我会尽量及时回复。
如果有没有提到的知识点欢迎提出,我会及时补全。

三种线程操作

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 操作对象

  • 串行异步、同步队列保证在同一线程中顺序执行。
  • DispatchWorkItemopen 类,不能继承创建子类
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)
}

总结:异步会重新创建线程

您的一举一动都是对我的莫大支持

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Swift 的标准字典类型 `Dictionary` 并不是线程安全的,因此在并发场景下使用可能会出现问题。为了实现线程安全的字典,可以使用 `DispatchQueue` 和 `ConcurrentDictionary`。 下面是一个简单的线程安全字典的实现: ```swift final class ConcurrentDictionary<Key: Hashable, Value> { private let queue = DispatchQueue(label: "ConcurrentDictionary", attributes: .concurrent) private var dictionary: [Key: Value] = [:] subscript(key: Key) -> Value? { get { var result: Value? queue.sync { result = dictionary[key] } return result } set(newValue) { queue.async(flags: .barrier) { self.dictionary[key] = newValue } } } var keys: [Key] { var result: [Key] = [] queue.sync { result = Array(dictionary.keys) } return result } var values: [Value] { var result: [Value] = [] queue.sync { result = Array(dictionary.values) } return result } } ``` 这个字典的实现使用了一个 `DispatchQueue` 来保证对字典的访问是线程安全的。`ConcurrentDictionary` 实现了 `subscript`、`keys` 和 `values` 方法,它们都采用了不同的 dispatch 方法来执行读取和写入操作。其中,`subscript` 方法采用了 `sync` 方法,它会等待队列中所有任务执行完毕后才返回结果;而 `keys` 和 `values` 方法使用了 `async` 方法并传递了 `.barrier` 标志,它会等待队列中所有读取操作完成后再执行写入操作。 使用时,可以像使用普通字典一样使用这个线程安全字典,例如: ```swift let dict = ConcurrentDictionary<String, Int>() dict["one"] = 1 dict["two"] = 2 print(dict.keys) print(dict.values) ``` 需要注意的是,这个线程安全字典的实现并不是最优的,如果需要更高的性能,可以考虑使用更复杂的数据结构,例如 `ConcurrentHashmap`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值