33.多线程之GCD
2016-03-19 12:00
459 查看
GCD
GCD即Grand Central Dispatch, 是苹果推荐使用的多线程技术, 它可以充分利用多核.它通过队列来安排任务, GCD队列分为三种:全局队列
主队列
串行队列
下面我们学习它们
1. 全局队列
全局队列是一个并发队列. 我们来创建一个全局队列:let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 第一个参数:DISPATCH_QUEUE_PRIORITY_HIGH,DISPATCH_QUEUE_PRIORITY_DEFAULT,DISPATCH_QUEUE_PRIORITY_LOW,DISPATCH_QUEUE_PRIORITY_BACKGROUND中的一个,它指定优先级, 一般用DISPATCH_QUEUE_PRIORITY_DEFAULT即可 第二个参数: 苹果留着的以后扩展用的, 传0即可, 传其它值可能会返回空
2. 串行队列
串行就是一个接一个的执行,只会开一个线程.串行队列要自己创建:let queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL) 第一个参数: 队列名字, 随意取 第二个参数: 队列类型, 可以是DISPATCH_QUEUE_SERIAL(串行队列),DISPATCH_QUEUE_CONCURRENT(并行队列)
3. 主队列
它是一个特殊的串行队列, 它的任务都在主线程中运行,程序运行,主线程就已经运行,而主队列也就已经存在, 我可以直接获取:let queue = dispatch_get_main_queue()
4. GCD的任务派遣方式
GCD的任务派遣方式有两种: dispatch_async 和 dispatch_sync现在我们实现一个例子, 对上面的三种队列,我们分别使用同步和异步的派遣方式,来观察线程的开启情况:
import UIKit class ViewController: UIViewController { var mainQueue: dispatch_queue_t! var globalQueue: dispatch_queue_t! var serialQueue: dispatch_queue_t! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. // 全局队列 globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) // 串行队列 serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL) // 主队列 mainQueue = dispatch_get_main_queue() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func globalQueueAsyncAction(sender: AnyObject) { dispatch_async(globalQueue) { () -> Void in print("全局队列_异步派遣: \(NSThread.currentThread())") } } @IBAction func globalQueueSyncAction(sender: AnyObject) { dispatch_sync(globalQueue) { () -> Void in print("全局队列_同步派遣: \(NSThread.currentThread())") } } @IBAction func serialQueueAsyncAction(sender: AnyObject) { dispatch_async(serialQueue) { () -> Void in print("串行队列_异步派遣: \(NSThread.currentThread())") } } @IBAction func serialQueueSyncAction(sender: AnyObject) { dispatch_sync(serialQueue) { () -> Void in print("串行队列_同步派遣: \(NSThread.currentThread())") } } @IBAction func mainQueueAsyncAction(sender: AnyObject) { dispatch_async(mainQueue) { () -> Void in print("主队列_异步派遣: \(NSThread.currentThread())") } } @IBAction func mainQueueSyncAction(sender: AnyObject) { dispatch_sync(mainQueue) { () -> Void in print("主队列_同步派遣: \(NSThread.currentThread())") } } }
然后我们查看不同的情况的打印的值,每个按钮点上3遍:
全局队列_异步派遣: <NSThread: 0x7f90e0fac470>{number = 2, name = (null)} 全局队列_异步派遣: <NSThread: 0x7f90e0fac470>{number = 2, name = (null)} 全局队列_异步派遣: <NSThread: 0x7f90e0fac470>{number = 2, name = (null)}
我们可以看出: globalQueue和dispatch_async的组合会开启新的线程
全局队列_同步派遣: <NSThread: 0x7f90e0e04340>{number = 1, name = main} 全局队列_同步派遣: <NSThread: 0x7f90e0e04340>{number = 1, name = main} 全局队列_同步派遣: <NSThread: 0x7f90e0e04340>{number = 1, name = main}
我们可以看出: globalQueue和dispatch_sync的组合不会开启新的线程,就在主线程中运行
串行队列_异步派遣: <NSThread: 0x7f90e0fac470>{number = 3, name = (null)} 串行队列_异步派遣: <NSThread: 0x7f90e0fac470>{number = 3, name = (null)} 串行队列_异步派遣: <NSThread: 0x7f90e0fac470>{number = 3, name = (null)}
我们可以看出: serialQueue和dispatch_async的组合会开启新的线程
串行队列_同步派遣: <NSThread: 0x7f90e0e04340>{number = 1, name = main} 串行队列_同步派遣: <NSThread: 0x7f90e0e04340>{number = 1, name = main} 串行队列_同步派遣: <NSThread: 0x7f90e0e04340>{number = 1, name = main}
我们可以看出: serialQueue和dispatch_sync的组合不会开启新的线程,就在主线程中运行
主队列_异步派遣: <NSThread: 0x7f90e0e04340>{number = 1, name = main} 主队列_异步派遣: <NSThread: 0x7f90e0e04340>{number = 1, name = m b8c7 ain} 主队列_异步派遣: <NSThread: 0x7f90e0e04340>{number = 1, name = main}
我们可以看出: mainQueue和dispatch_async的组合不会开启新的线程,就在主线程中运行
主队列_同步派遣即mainQueue和dispatch_sync的组合, 模拟器直接卡死了.
现在我们可以总结一下了:
globalQueue serialQueue mainQueue dispatch_async 开新线程运行 开新线程运行 主线程运行 dispatch_sync 主线程运行 主线程运行 模拟器卡死
一般的情况:
执行耗时操作, dispatch_async + globalQueue, 然后耗时操作完成, 更新UI的时候dispatch_async + mainQueue
5. GCD的组操作
当要监听一系列任务都执行完成时,如下载多个音乐完成后,我们要给个提示,这就要使用GCD的组了.我们在storyboard中拖拽一个按钮,添加监听方法:
@IBAction func groupAction(sender: AnyObject) { let group = dispatch_group_create() dispatch_group_async(group, globalQueue) { () -> Void in print("下载音乐1, \(NSThread.currentThread())") } dispatch_group_async(group, globalQueue) { () -> Void in print("下载音乐2, \(NSThread.currentThread())") } dispatch_group_async(group, globalQueue) { () -> Void in print("下载音乐3, \(NSThread.currentThread())") } dispatch_group_notify(group, globalQueue) { () -> Void in print("下载完成") } }
运行程序, 点击按钮:
下载音乐2, <NSThread: 0x7f966bf38ee0>{number = 3, name = (null)} 下载音乐1, <NSThread: 0x7f966bc28ae0>{number = 2, name = (null)} 下载音乐3, <NSThread: 0x7f966bd28190>{number = 4, name = (null)} 下载完成
可以发现, 异步任务的顺序是不确定的, 但是使用群组可以在所有任务执行完成后执行一个block.
6. 完整代码
import UIKit
class ViewController: UIViewController {
var mainQueue: dispatch_queue_t!
var globalQueue: dispatch_queue_t!
var serialQueue: dispatch_queue_t!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// 全局队列
globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
// 串行队列
serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL)
// 主队列
mainQueue = dispatch_get_main_queue()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func globalQueueAsyncAction(sender: AnyObject) {
// 开启新的线程
dispatch_async(globalQueue) { () -> Void in
print("全局队列_异步派遣: \(NSThread.currentThread())")
}
}
@IBAction func globalQueueSyncAction(sender: AnyObject) {
// 运行在主线程
dispatch_sync(globalQueue) { () -> Void in
print("全局队列_同步派遣: \(NSThread.currentThread())")
}
}
@IBAction func serialQueueAsyncAction(sender: AnyObject) {
dispatch_async(serialQueue) { () -> Void in
print("串行队列_异步派遣: \(NSThread.currentThread())")
}
}
@IBAction func serialQueueSyncAction(sender: AnyObject) {
dispatch_sync(serialQueue) { () -> Void in
print("串行队列_同步派遣: \(NSThread.currentThread())")
}
}
@IBAction func mainQueueAsyncAction(sender: AnyObject) {
dispatch_async(mainQueue) { () -> Void in
print("主队列_异步派遣: \(NSThread.currentThread())")
}
}
@IBAction func mainQueueSyncAction(sender: AnyObject) {
dispatch_sync(mainQueue) { () -> Void in
print("主队列_同步派遣: \(NSThread.currentThread())")
}
}
@IBAction func groupAction(sender: AnyObject) { let group = dispatch_group_create() dispatch_group_async(group, globalQueue) { () -> Void in print("下载音乐1, \(NSThread.currentThread())") } dispatch_group_async(group, globalQueue) { () -> Void in print("下载音乐2, \(NSThread.currentThread())") } dispatch_group_async(group, globalQueue) { () -> Void in print("下载音乐3, \(NSThread.currentThread())") } dispatch_group_notify(group, globalQueue) { () -> Void in print("下载完成") } }
}
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- Apple Swift学习教程
- 苹果与Siri的七年之痒:“宫斗”戏码不断上演
- 介绍 Fedora 上的 Swift
- 央视新闻报道XcodeGhost事件
- C#实现多线程的同步方法实例分析
- 浅谈chuck-lua中的多线程
- 原生JS仿苹果任务栏菜单,放大效果的菜单
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- 解析C#多线程编程中异步多线程的实现及线程池的使用
- C#多线程学习之(六)互斥对象用法实例
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- 分享我在工作中遇到的多线程下导致RCW无法释放的问题
- C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步的方法