iOS多线程 串行队列、并发队列以及同步执行、异步执行

2019/6/26 posted in  Swift

关键词的理解

1. 进程

正在运行的程序被称为进程,负责程序运行的内存分配,每一个进程都有独立的虚拟内存空间

2. 线程

线程是进程中最小的执行单元,一个进程可以有多条线程,但是至少包含一条线程,被称为主线程。线程里有非常多的任务。

  1. 同一时间单核CPU只能执行一个线程,多线程是CPU快速在多个线程之间切换,造成多个线程同时执行的假象
  2. 多核CPU是真的同时处理多个线程
3. 并行

充分利用计算机的多核,在多个线程上同步进行

4. 并发

在一条线程上通过快速切换,让人感觉在同步进行

5. 任务

任务分为同步任务和异步任务,任务是在线程中执行的

  1. 同步任务:同步任务不会开启新的线程,按顺序执行,执行完一个再执行下一个,需要等待。

    开启同步任务使用GCD中的sync

  2. 异步任务:异步任务是彼此独立的,不需要等待某一件事完成后再工作,无法确定任务的执行顺序。执行异步任务会创建新的线程。异步是最终目的,多线程只是我们实现异步的一种手段。

    开启异步任务使用GCD中的async

6. 队列

是先进先出的线性表。

  1. 串行队列:队列中的任务一个一个的执行,前一个任务不执行完毕,队列不会调度。
  2. 并行队列:只要有空闲的线程,队列就会调度当前任务,交给线程去执行,不用等待上一个任务执行完毕。
  3. 全局队列:系统开发的,是并行队列,但调用时没法确认操作所在队列
  4. 主队列:每一个应用程序对应唯一一个主队列,UI操作必须在主线程内,否则可能出现崩溃

队列与任务的组合

1. 串行队列同步执行

不会创建新线程,任务一个一个按顺序执行。

let serialQueue = DispatchQueue.init(label: "test") // 串行队列
for i in 0..<10 {
    serialQueue.sync {
        Thread.sleep(forTimeInterval: 1)
        print("\(Date()) i \(i), current theard: \(Thread.current)")
    }
}

*w779

2. 并行队列同步执行

不用等待一个任务执行完毕才开始调度下一个任务,但是同步任务不会开启新的线程,所以也是一个一个的执行。

let concurrentQueue = DispatchQueue.init(label: "test", attributes: .concurrent) // 并行队列
for i in 0..<10 {
    concurrentQueue.sync {
        Thread.sleep(forTimeInterval: 1)
        print("\(Date()) i \(i), current theard: \(Thread.current)")
    }
}

*w780

3. 串行队列异步执行

按顺序来调度任务,任务会创建一个新的线程(线程5)来执行

for i in 0..<10 {
    serialQueue.async {
        Thread.sleep(forTimeInterval: 1)
        print("\(Date()) 执行任务\(i), current theard: \(Thread.current)")
    }
}

*w786

4. 并行队列异步执行

会创建多个线程,操作并发无序执行。

for i in 0..<10 {  
    concurrentQueue.async {
        Thread.sleep(forTimeInterval: 1)
        print("\(Date()) 执行任务\(i), current theard: \(Thread.current)")
    }
}

*w800

5. 全局队列同步执行

操作不会新建线程,操作顺序执行

for i in 0..<10 {
    DispatchQueue.global().sync {
        Thread.sleep(forTimeInterval: 1)
        print("\(Date()) 执行任务\(i), current theard: \(Thread.current)")
    }
}

*w777

6. 全局队列异步执行

会创建多个线程,操作无序执行

for i in 0..<10 { 
    DispatchQueue.global().async {
        Thread.sleep(forTimeInterval: 1)
        print("\(Date()) 执行任务\(i), current theard: \(Thread.current)")
    }
}

*w795

7. 主线程同步执行

主线程不会结束,主队列中的同步操作永远不会被执行,会死锁。

print("1")

DispatchQueue.main.sync {
    print("2")
}

print("3")