IOS多线程-GCD使用

By | 2015年5月21日

IOS多线程编程中,GCD是一个很方便的库,它的核心是GCD队列,所有操作都围绕着队列。

1、GCD中的三种队列

GCD中三种队列:主队列、全局队列、自定义队列。

 //创建一个全局队列,队列的优先级(Priority)为Default,第二个参数暂时保留,传0即可
let myQueue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

 //创建一个自定义队列,第一个参数是队列的标识名字,第二个参数指定队列是并发队列(concurrent),如果是串行队列的话是serial
let myQueue2: dispatch_queue_t = dispatch_queue_create("队列标识字符串", DISPATCH_QUEUE_CONCURRENT)

 //获取当前主队列
let myQueue3: dispatch_queue_t = dispatch_get_main_queue()

2、串行队列和并发队列

在使用自定义队列时,需要指定队列是并发的还是串行的,使用并发的居多,参数是:

//串行队列
DISPATCH_QUEUE_SERIAL
//并发队列
DISPATCH_QUEUE_CONCURRENT

3、队列的优先级

在创建全局队列时,需要指定队列的优先级,一共有4种级别:

//优先级从低到高,一般使用Default即可
DISPATCH_QUEUE_PRIORITY_BACKGROUND
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_HIGH

4、使用异步方法执行队列

//使用异步方式运行调用队列,主程序遇到后会继续执行后面的代码
dispatch_async(myQueue){
    //队列中需要执行的任务
    self.setLabel()
}

5、在主队列中更新UI

多线程编程时,一定要在主线程也就是主队列中更新UI,所以凡是需要修改界面内容都要在main_queue中操作

//在主线程中更新UI控件
dispatch_async(dispatch_get_main_queue()){
    self.lblString.text = "更新的内容"
}

6、队列延迟

使用dispatch_after可以延迟一段时间执行队列中的任务。

//队列延迟2秒执行
let time:dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, (Int64)(NSEC_PER_SEC * 2))
dispatch_after(time, dispatch_get_main_queue()) {
    self.lblString.text = "队列延迟操作了"
}

第一个参数是dispatch_time_t,作为一个时间对象,在dispatch_time中有两种时间模式:

DISPATCH_TIME_FOREVER
DISPATCH_TIME_NOW

7、队列重复(循环)

//队列的重复,循环3次,放在并发的全局队列中,闭包中有一个参数,包含了当前循环次数的索引值
dispatch_apply(3, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    println($0)
}

8、使用Group调度组来管理队列,基于notify来回调事件方法

//自定义的队列
var myQueue: dispatch_queue_t?
override func viewDidLoad() {
    super.viewDidLoad()

    self.myQueue = dispatch_queue_create("lijialong.thread", DISPATCH_QUEUE_CONCURRENT)
}
//使用调度组对任务管理,完成后使用notify回调更新Label
private func use_Dispatch_Group_AsyncNotify(){
    //创建一个调度组
    var myGroup = dispatch_group_create()

    //使用自定义队列,异步调度组
    dispatch_group_async(myGroup, myQueue!){
        var data1 = NSData(contentsOfURL: NSURL(string: "hhttp://b.hiphotos.baidu.com/image/w%3D310/sign=e22578ddd462853592e0d420a0ee76f2/b03533fa828ba61ed1a6ca004034970a304e5950.jpg")!)
        self.updateImageData(imgView: self.img1, data: data1!)
    }
    dispatch_group_async(myGroup, myQueue!){
        var data2 = NSData(contentsOfURL: NSURL(string: "http://e.hiphotos.baidu.com/image/w%3D310/sign=19025f7e9058d109c4e3afb3e158ccd0/fd039245d688d43f43c2adf27f1ed21b0ef43b42.jpg")!)
        self.updateImageData(imgView: self.img2, data: data2!)
    }

    dispatch_group_notify(myGroup, dispatch_get_main_queue()){
        self.lbl.text = "Load Finish"
    }

}
//在主线程中更新UI
private func updateImageData(#imgView:UIImageView,data:NSData){
    dispatch_async(dispatch_get_main_queue()){
        imgView.image = UIImage(data: data)

    }
}

9、使用Group调度组管理队列,基于wait来等待执行完成,会阻塞主线程

private func use_Dispatch_Group_Wait(){

    var myGroup = dispatch_group_create()

    dispatch_group_async(myGroup, myQueue!){
        var data1 = NSData(contentsOfURL: NSURL(string: "hhttp://b.hiphotos.baidu.com/image/w%3D310/sign=e22578ddd462853592e0d420a0ee76f2/b03533fa828ba61ed1a6ca004034970a304e5950.jpg")!)
        self.updateImageData(imgView: self.img1, data: data1!)
    }

    dispatch_group_async(myGroup, myQueue!){
        var data2 = NSData(contentsOfURL: NSURL(string: "http://e.hiphotos.baidu.com/image/w%3D310/sign=19025f7e9058d109c4e3afb3e158ccd0/fd039245d688d43f43c2adf27f1ed21b0ef43b42.jpg")!)
        self.updateImageData(imgView: self.img2, data: data2!)
    }
    //等待group完成后,再运行后面,会阻塞主线程!
    dispatch_group_wait(myGroup, DISPATCH_TIME_FOREVER)

    lbl.text = "Load Finish"
}

10、队列暂停与恢复

//暂停  只能对自定义队列操作,不能对主线程和全局队列操作
//  只能暂停还未加载到队列中的任务,已经加载的无法暂停,可以使用dispatch_after延迟队列解决
private func suspend(){
    dispatch_suspend(myQueue!)
}
//恢复
private func resume(){
    dispatch_resume(myQueue!)
}