iOS开发高级

GCD Swift 用法

2019-03-29  本文已影响0人  hwhjxjs

参考https://blog.csdn.net/Hello_Hwc/article/details/54293280

进程/线程

进程:进程指在系统中能独立运行并作为资源分配的基本单位,它是由一组机器指令、数据和堆栈等组成的,是一个能独立运行的活动实体。
线程:线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行。
操作系统引入进程的目的:为了使多个程序能并发执行,以提高资源的利用率和系统的吞吐量。
操作系统引入线程的目的:在操作系统中再引入线程,则是为了减少程序在并发执行时所付出的时空开销,使OS具有更好的并发性。多线程技术可以提高程序的执行效率。

1. Gcd的概念

Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并发任务。在 Mac OS X 10.6 雪豹中首次推出,也可在 iOS 4 及以上版本使用

为什么要用 GCD 呢?

因为 GCD 有很多好处啊,具体如下:

2. GCD 任务和队列

学习 GCD 之前,先来了解 GCD 中两个核心概念:任务和队列。
任务:就是执行操作的意思,换句话说就是你在线程中执行的那段代码。在 GCD 中是放在 block 中的。执行任务有两种方式:同步执行(sync)和异步执行(async)。两者的主要区别是:是否等待队列的任务执行结束,以及是否具备开启新线程的能力。

注意: 异步执行(async) 虽然具有开启新线程的能力,但是并不一定开启新线程。这跟任务所指定的队列类型有关(下面会讲)。

队列(Dispatch Queue):这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表,采用 FIFO(先进先出)的原则,即新任务总是被插入到队列的末尾,而读取任务的时候总是从队列的头部开始读取。每读取一个任务,则从队列中释放一个任务。队列的结构可参考下图:

队列

在 GCD 中有两种队列:串行队列和并发队列。两者都符合 FIFO(先进先出)的原则。两者的主要区别是:执行顺序不同,以及开启线程数不同。

注意:并发队列 的并发功能只有在异步(dispatch_async)函数下才有效

两者具体区别如下两图所示。



3. GCD 的使用步骤

3.1 GCD 的使用步骤其实很简单,只有两步。

1.创建一个队列(串行队列或并发队列)
2.将任务追加到任务的等待队列中,然后系统就会根据任务类型执行任务(同步执行或异步执行)

let queue = DispatchQueue(label: "hwhQuene1")  //表示串行队列
let queue = DispatchQueue(label: "hwhQuene1",  attributes: .concurrent)  //并行队列
queue.async {
   print("线程1运行")
}
queue.sync {
   print("线程2运行")
}
let mainQuene = DispatchQueue.main
let globalQuene = DispatchQueue.global()

3.2 任务的创建方法

GCD 提供了同步执行任务的创建方法sync和异步执行任务创建方法async。

queue.async {
   print("线程1运行")
}
queue.sync {
   print("线程2运行")
}

虽然使用 GCD 只需两步,但是既然我们有两种队列(串行队列/并发队列),两种任务执行方式(同步执行/异步执行),那么我们就有了四种不同的组合方式。这四种不同的组合方式是:

1.同步执行 + 并发队列
2.异步执行 + 并发队列
3.同步执行 + 串行队列
4.异步执行 + 串行队列

并发串发

4. GCD 的基本使用

先来讲讲并发队列的两种执行方式。

4.1 同步执行 + 并发队列

    func syncConcurrent()  {
        
        print("syncConcurrent---%@",Thread.current)
        print("syncConcurrent--begin")
        
        let queue = DispatchQueue(label: "hwhQuene1",  attributes: .concurrent)
        queue.sync {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程1运行---%@",Thread.current)
            }
            
        }
        
        queue.sync {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程2运行---%@",Thread.current)
            }
            
        }
        
        queue.sync {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程3运行---%@",Thread.current)
            }
            
        }
        
         print("syncConcurrent--end")
    }

输出结果
syncConcurrent---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
syncConcurrent--begin
线程1运行---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
线程1运行---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
线程1运行---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
线程2运行---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
线程2运行---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
线程2运行---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
线程3运行---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
线程3运行---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
线程3运行---%@ <NSThread: 0x281b9ae40>{number = 1, name = main}
syncConcurrent--end

从同步执行 + 并发队列中可看到:

4.2 异步执行 + 并发队列

可以开启多个线程,任务交替(同时)执行。

    func syncConcurrent()  {
        
        print("syncConcurrent---%@",Thread.current)
        print("syncConcurrent--begin")
        
        let queue = DispatchQueue(label: "hwhQuene1",  attributes: .concurrent)
        queue.async {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程1运行---%@",Thread.current)
            }
            
        }
        
        queue.async {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程2运行---%@",Thread.current)
            }
            
        }
        
        queue.async {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程3运行---%@",Thread.current)
            }
            
        }
        
         print("syncConcurrent--end")
    }

syncConcurrent---%@ <NSThread: 0x28386ee40>{number = 1, name = main}
syncConcurrent--begin
syncConcurrent--end
线程2运行---%@ <NSThread: 0x283803d00>{number = 4, name = (null)}
线程1运行---%@ <NSThread: 0x283835200>{number = 3, name = (null)}
线程3运行---%@ <NSThread: 0x283837540>{number = 5, name = (null)}
线程2运行---%@ <NSThread: 0x283803d00>{number = 4, name = (null)}
线程1运行---%@ <NSThread: 0x283835200>{number = 3, name = (null)}
线程3运行---%@ <NSThread: 0x283837540>{number = 5, name = (null)}
线程2运行---%@ <NSThread: 0x283803d00>{number = 4, name = (null)}
线程1运行---%@ <NSThread: 0x283835200>{number = 3, name = (null)}
线程3运行---%@ <NSThread: 0x283837540>{number = 5, name = (null)}

在异步执行 + 并发队列中可以看出:

接下来再来讲讲串行队列的两种执行方式。

4.3 同步执行 + 串行队列

func syncSerial()  {
        
        print("syncConcurrent---%@",Thread.current)
        print("syncConcurrent--begin")
        
        let queue = DispatchQueue(label: "hwhQuene1")
        queue.sync {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程1运行---%@",Thread.current)
            }
            
        }
        
        queue.sync {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程2运行---%@",Thread.current)
            }
            
        }
        
        queue.sync {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程3运行---%@",Thread.current)
            }
            
        }
        
        print("syncConcurrent--end")
    }

syncConcurrent---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
syncConcurrent--begin
线程1运行---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
线程1运行---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
线程1运行---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
线程2运行---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
线程2运行---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
线程2运行---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
线程3运行---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
线程3运行---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
线程3运行---%@ <NSThread: 0x28323ee00>{number = 1, name = main}
syncConcurrent--end

在同步执行 + 串行队列可以看到:

4.4 异步执行 + 串行队列

 func asyncSerial()  {
        
        print("syncConcurrent---%@",Thread.current)
        print("syncConcurrent--begin")
        
        let queue = DispatchQueue(label: "hwhQuene1")
        queue.async {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程1运行---%@",Thread.current)
            }
            
        }
        
        queue.async {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程2运行---%@",Thread.current)
            }
            
        }
        
        queue.async {
            for _ in 0...2{
                Thread.sleep(forTimeInterval: 2)
                print("线程3运行---%@",Thread.current)
            }
            
        }
        
        print("syncConcurrent--end")
    }

syncConcurrent---%@ <NSThread: 0x282032e40>{number = 1, name = main}
syncConcurrent--begin
syncConcurrent--end
线程1运行---%@ <NSThread: 0x282073e80>{number = 4, name = (null)}
线程1运行---%@ <NSThread: 0x282073e80>{number = 4, name = (null)}
线程1运行---%@ <NSThread: 0x282073e80>{number = 4, name = (null)}
线程2运行---%@ <NSThread: 0x282073e80>{number = 4, name = (null)}
线程2运行---%@ <NSThread: 0x282073e80>{number = 4, name = (null)}
线程2运行---%@ <NSThread: 0x282073e80>{number = 4, name = (null)}
线程3运行---%@ <NSThread: 0x282073e80>{number = 4, name = (null)}
线程3运行---%@ <NSThread: 0x282073e80>{number = 4, name = (null)}
线程3运行---%@ <NSThread: 0x282073e80>{number = 4, name = (null)}

在异步执行 + 串行队列可以看到:

上一篇 下一篇

猜你喜欢

热点阅读