您的位置:首页 > 移动开发 > Swift

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("下载完成") } }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息