swift多线程编程之GCD

2017-04-28  本文已影响0人  张义飞

什么是GCD

DispatchQueue.global().async {
            
            /*
                这里执行耗时操作
             */
            
            var sum = 0
            for i in 0...100 {
                print("global线程:\(Thread.current)")
                sum += i
            }
            
            /*
             这里刷新UI
             */
            
            DispatchQueue.main.async {
                print("main线程:\(Thread.current)")
                print(sum)
            }
        }
self.performSelector(inBackground: #selector(doWork), with: nil)

    func doWork() {
        print("后台处理中")
        
        self.performSelector(onMainThread: #selector(finishDone), with: nil, waitUntilDone: true)
    }
    
    func finishDone() {
        print("后台处理完成")
    }

多线程编程

串行队列:单个线程,等待上个任务执行完毕,才往后执行

并行队列:多个线程,可以同时执行

DispatchQueue.main.async {
            print("当前线程\(Thread.current)------->1")
        }
        DispatchQueue.main.async {
            print("当前线程\(Thread.current)------->2")
        }
        DispatchQueue.main.async {
            print("当前线程\(Thread.current)------->3")
        }
        DispatchQueue.main.async {
            print("当前线程\(Thread.current)------->4")
        }

-打印结果(main队列只有一个线程所以是串行队列)

  1. 当前线程<NSThread: 0x7b257510>{number = 1, name = main}------->1
  2. 当前线程<NSThread: 0x7b257510>{number = 1, name = main}------->2
  3. 当前线程<NSThread: 0x7b257510>{number = 1, name = main}------->3
  4. 当前线程<NSThread: 0x7b257510>{number = 1, name = main}------->4
DispatchQueue.global().async {
            print("当前线程\(Thread.current)------->1")
        }
        DispatchQueue.global().async {
            print("当前线程\(Thread.current)------->2")
        }
        DispatchQueue.global().async {
            print("当前线程\(Thread.current)------->3")
        }
        DispatchQueue.global().async {
            print("当前线程\(Thread.current)------->4")
        }
  1. 当前线程<NSThread: 0x7d160c10>{number = 3, name = (null)}------->3
  2. 当前线程<NSThread: 0x7bfa9dd0>{number = 2, name = (null)}------->1
  3. 当前线程<NSThread: 0x7d15de60>{number = 4, name = (null)}------->4
  4. 当前线程<NSThread: 0x7d153b90>{number = 5, name = (null)}------->2

如何创建队列

let queue = DispatchQueue(label: "myQueue")
        queue.async {
            print("当前线程\(Thread.current)------->1")
        }
        queue.async {
            print("当前线程\(Thread.current)------->2")
        }
        queue.async {
            print("当前线程\(Thread.current)------->3")
        }
        queue.async {
            print("当前线程\(Thread.current)------->4")
            }
// 打印结果
1. 当前线程<NSThread:0x7c0825f0>{number = 2, name = (null)}------->1
2. 当前线程<NSThread: 0x7c0825f0>{number = 2, name = (null)}------->2
3. 当前线程<NSThread: 0x7c0825f0>{number = 2, name = (null)}------->3
4. 当前线程<NSThread: 0x7c0825f0>{number = 2, name = (null)}------->4
let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
  1. User Interactive 和用户交互相关,比如动画等等优先级最高。比如用户连续拖拽的计算
  2. User Initiated 需要立刻的结果,比如push一个ViewController之前的数据计算
  3. Utility 可以执行很长时间,再通知用户结果。比如下载一个文件,给用户下载进度。
  4. Background 用户不可见,比如在后台存储大量数据
let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
        queue.async {
            print("当前线程\(Thread.current)------->1")
        }
        queue.async {
            print("当前线程\(Thread.current)------->2")
        }
        //切换队列
        queue.setTarget(queue: DispatchQueue.main)
        
        queue.async {
            print("当前线程\(Thread.current)------->3")
        }
        queue.async {
            print("当前线程\(Thread.current)------->4")
        }
  1. 当前线程<NSThread: 0x7bc2d970>{number = 2, name = (null)}------->2
  2. 当前线程<NSThread: 0x7b63fe10>{number = 3, name = (null)}------->1
  3. 当前线程<NSThread: 0x7b6215b0>{number = 1, name = main}------->3
  4. 当前线程<NSThread: 0x7b6215b0>{number = 1, name = main}------->4
DispatchQueue.main.asyncAfter(deadline: .now() + DispatchTimeInterval.seconds(3)) { //不是三秒后执行该任务,而是三秒后添加到改队列
            //执行的代码
        }
let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.initiallyInactive, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
        queue.async {
            print("当前线程\(Thread.current)------->1")
        }
        queue.async {
            print("当前线程\(Thread.current)------->2")
        }
        queue.async {
            print("当前线程\(Thread.current)------->3")
        }
        queue.async {
            print("当前线程\(Thread.current)------->4")
            DispatchQueue.main.async {
                print("执行完了")
            }
        }
  1. 当前线程<NSThread: 0x7a66cea0>{number = 2, name = (null)}------->1
  2. 当前线程<NSThread: 0x7a66cea0>{number = 2, name = (null)}------->2
  3. 当前线程<NSThread: 0x7a66cea0>{number = 2, name = (null)}------->3
  4. 当前线程<NSThread: 0x7a66cea0>{number = 2, name = (null)}------->4
  5. 执行完了
let group = DispatchGroup()
        let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->1")
        })
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->2")
        })
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->3")
        })
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->4")
        })
        let workItem = DispatchWorkItem { 
            print("执行完成")
        }  group.notify(queue: queue, work: workItem)
  1. 当前线程<NSThread: 0x78e49ae0>{number = 2, name = (null)}------->2
  2. 当前线程<NSThread: 0x790a4710>{number = 3, name = (null)}------->1
  3. 当前线程<NSThread: 0x78e53d00>{number = 5, name = (null)}------->3
  4. 当前线程<NSThread: 0x78e43b60>{number = 4, name = (null)}------->4
  5. 执行完成

和notify不同的是wait是等待一段时间,不管队列的任务是否都完成了,都会调用。

let workItem = DispatchWorkItem { 
            print("开始干活\(Thread.current)")
        }
//        workItem.perform() //立即执行, 放到了当前main队列中
//        DispatchQueue.global().async(execute: workItem) //放到global队列中
        let group = DispatchGroup()
        let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->1")
            queue.async(execute: {
                print("当前线程\(Thread.current)------->2")
            })
            queue.async(execute: {
                print("当前线程\(Thread.current)------->3")
            })
        })
        let workItem = DispatchWorkItem {
            print("done")
        }
        group.notify(queue: queue, work: workItem)
  1. 当前线程<NSThread: 0x7b967590>{number = 2, name = (null)}------->1
  2. done
  3. 当前线程<NSThread: 0x797807d0>{number = 1, name = main}------->2
  4. 当前线程<NSThread: 0x7b8bd8b0>{number = 3, name = (null)}------->3
let group = DispatchGroup()
        let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
        queue.async(group: group, execute: {
            print("当前线程\(Thread.current)------->1")
            
            group.enter()
            queue.async(execute: {
                group.leave()
                print("当前线程\(Thread.current)------->2")
            })
            
            group.enter()
            queue.async(execute: {
                print("当前线程\(Thread.current)------->3")
                group.leave()
            })
            
        })
        let workItem = DispatchWorkItem {
            print("done")
        }
        group.notify(queue: queue, work: workItem)
  1. 当前线程<NSThread: 0x7a95e9e0>{number = 2, name = (null)}------->1
  2. 当前线程<NSThread: 0x7a95e9e0>{number = 2, name = (null)}------->2
  3. 当前线程<NSThread: 0x7a963a70>{number = 3, name = (null)}------->3
  4. done
var array: [Int] = []
        
        for i in 0...100 {
            DispatchQueue.global().async(execute: { 
                array.append(i)
            })
        }
Demo(61868,0x38bc1c0) malloc: *** error for object 0x7ac34424: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
(lldb)
  1. 使用信号量解决
var array: [Int] = []
        let semaphore = DispatchSemaphore(value: 1)
        for i in 0...100 {
            DispatchQueue.global().async(execute: {
                
                /*
                    wait 等待信号量semaphore >= 1时执行
                    wait返回时 semaphore 减1
                 */
                _ = semaphore.wait(wallTimeout: .distantFuture)
                
                array.append(i) //只会同时被一个线程访问
                
                /*
                 signal semaphore 加1
                 */
                semaphore.signal()
            })
        }
        DispatchQueue.main.async {
            print(array.count)
        }
let lock = NSLock()
        var array: [Int] = []
        
        for i in 0...100 {
            DispatchQueue.global().async(execute: {
                lock.lock()
                array.append(i)
                lock.unlock()
            })
        }
        DispatchQueue.main.async {
            print(array.count)
        }

死锁(线程之间互相等待对方执行完之后才能接着执行)

DispatchQueue.main.sync {
            print("死锁了")
        }

DispatchSource 调度源

它的作用是当有一些特定的较底层的系统事件发生时,调度源会捕捉到这些事件,然后可以做其他的逻辑处理,调度源有多种类型,分别监听对应类型的系统事件。我们来看看它都有哪些类型
  1. DISPATCH_SOURCE_TYPE_DATA_ADD:属于自定义事件,可以通过dispatch_source_get_data函数获取事件变量数据,在我们自定义的方法中可以调用dispatch_source_merge_data函数向Dispatch Source设置数据,下文中会有详细的演示。
  2. DISPATCH_SOURCE_TYPE_DATA_OR:属于自定义事件,用法同上面的类型一样。
  3. DISPATCH_SOURCE_TYPE_MACH_SEND:Mach端口发送事件。
  4. DISPATCH_SOURCE_TYPE_MACH_RECV:Mach端口接收事件。
  5. DISPATCH_SOURCE_TYPE_PROC:与进程相关的事件。
  6. DISPATCH_SOURCE_TYPE_READ:读文件事件。
  7. DISPATCH_SOURCE_TYPE_WRITE:写文件事件。
  8. DISPATCH_SOURCE_TYPE_VNODE:文件属性更改事件。
  9. DISPATCH_SOURCE_TYPE_SIGNAL:接收信号事件。
  10. DISPATCH_SOURCE_TYPE_TIMER:定时器事件。
  11. DISPATCH_SOURCE_TYPE_MEMORYPRESSURE:内存压力事件。
private var timer: DispatchSourceTimer!

        self.timer = DispatchSource.makeTimerSource(flags: DispatchSource.TimerFlags.strict, queue: DispatchQueue.global())
        self.timer.scheduleRepeating(deadline: .now(), interval: DispatchTimeInterval.seconds(1)) //每隔一秒执行下面的操作
        self.timer.setEventHandler {
            DispatchQueue.main.async(execute: {
                //回到主线程刷新UI
                print(Date())
            })
        }
        self.timer.resume()
private var dispatchDataSource: DispatchSourceUserDataAdd!

        var progress: UInt = 0
        self.dispatchDataSource = DispatchSource.makeUserDataAddSource(queue: DispatchQueue.main)
        self.dispatchDataSource.setEventHandler { 
            let data = UInt(self.dispatchDataSource.data) //获取数据中心的data
            progress += data
            print("上传任务进度:\(progress)")
        }
        self.dispatchDataSource.resume()
        
        for _ in 0...5 {
            DispatchQueue.global().async(execute: {
                print("异步处理任务")
                
                self.dispatchDataSource.add(data: 1) //将数组添加数据中心
            })
        }
异步处理任务
异步处理任务
异步处理任务
异步处理任务
异步处理任务
异步处理任务
上传任务进度:6
上一篇 下一篇

猜你喜欢

热点阅读