Description

Grand Central Dispatch
framework to automatically manage the threads' lifecycle: create, dispatch, reuse, dealloc

How to use

  • custom task
  • push into DispatchQueue, queue is FIFO, but not First in, First execute
  • wait DispatchQueue logic and run the task

queue determine how to run tasks

  • concurrent queue: execute by maxConcurrentCount
  • serial queue: execute one by one
  • async / sync determine create new thread or not
    • async: create new thread
    • sync: blocking current thread and execute in current thread
  • async, wait for DispatchQueue to run
  • sync, run in current thread at once

API

// 主队列:
//OBJECTIVE-C
dispatch_queue_t queue = ispatch_get_main_queue();


//OBJECTIVE-C

//串行队列
dispatch_queue_t queue= dispatch_queue_create("tk.bourne.testQueue", NULL);
dispatch_queue_t queue= dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_SERIAL);
//并行队列
dispatch_queue_t queue= dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_CONCURRENT);

// 全局并行队列
//OBJECTIVE-C
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// main queue
DispatchQueue.main.async { }
DispatchQueue.main.async(execute: ()->Void)

// global concurrent queue
DispatchQueue.global().async {}
DispatchQueue.global().async(execute: ()->Void)
DispatchQueue.global().async(execute: DispatchWorkItem)
DispatchQueue.global().asyncAfter(deadline: DispatchTime, execute: ()->Void)
DispatchQueue.global().asyncAfter(deadline: DispatchTIme, execute: DispatchWorkItem)


// create serial queue
let serialQueue = DispatchQueue(label: "serialQueue")
let serialQueue1 = DispatchQueue(__label: "serialQueue1", attr: nil)
// create concurrent queue
let concurrentQueue = DispatchQueue(label: "concurrentQueue1", attributes: .concurrent)

优势:

自动管理线程的生命周期(create,schedule,release)

GCD 核心: 任务 && 队列

  1. 定制任务
  2. 将任务添加队列中 FIFO, 但不一定谁先执行
    • Concurrent Queue(开启多个线程让多个任务同时执行)
    • Serial Queue (一个接一个执行)

async 和 sync决定能不能开启线程,

async 和 sync 决定要不要阻塞当前线程

queue决定如何执行任务

异步函数等会儿执行,同步函数马上执行, 并阻塞当前线程

GCD 主要方法:

  • DispatchQueue.queueName.sync { } //在当前线程之行,不具备开启新线程的能力
  • DispatchQueue.queueName.async {} //可能开启新线程

队列创建

类型

  • Concurrent Queue(允许开启多个线程让多个任务同时执行)
  • Serial Queue (一个接一个执行)

创建

dispatch_queue_t queue = dispatch_queue_create("name", DISPATCH_QUEUE_SERIAL/DISPATCH_QUEUE_CONCURENT);
// create serial queue
let serialQueue = DispatchQueue("serialQueue")
let serialQueue1 = DispatchQueue("SerialQueue1", DISPATCH_QUEUE_SERIAL)
// create concurrent queue
let concurrentQueue = DispatchQueue("ConcurrentQueue", DISPATCH_QUEUE_CONCURRENT)

全局队列

dispatch_get_global_queue(优先级, 0);//并发队列
dispatch_get_main_queue()//特殊的串行队列队列
DispatchQueue.main
DispatchQueue.global()

特殊

Main queue is serial,函数放到主队列异步也不会开启新线程

Main queue with sync task will cause Deadlock

GCD 其他函数

等待前面线程执行完再执行( For thread-safe)

dispatch_barrier_async(queue, block)

隔开任务,barrier前面的执行完在执行barrier的任务,barrier后面的在barrier执行完在执行

用global queue不行,必须自己建的队列

serial 队列用不着这么做,已经是串行一个个执行

// guarantee .barrier will run solely within the queue
// waiting for previous task done 
// blocking the rest tasks
let concurrentQueue = DispatchQueue(label: "concurrentQueue1", attributes: .concurrent)
concurrentQueue.async(flags: .barrier) {
        print("concurrentQueue barrier")
}

延后加入队列

dispatch_after(time, queue, block)
dispatch_once()static dispatch_once_t once; dispatch_once(once, block);
//里面的代码是线程安全的
//整个程序只加载一次,不能用于懒加载,懒加载是每个对象都能调用一次。反过来,用once,只有第一个对象能调用,
dispatch_apply(10, queue, block);
//同时遍历,queue必须是并发队列
DispatchQueue.global().asyncAfter(deadline: DispatchTime, execute: ()->Void)
DispatchQueue.global().asyncAfter(deadline: DispatchTIme, execute: DispatchWorkItem)

队列组 dispatch_group_async

dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, block);
dispatch_group_notify(group, queue, block(执行完了));
/// DispatchGroup
// Create DispatchGroup
let group = DispatchGroup()
let lastBlockGCD = { () -> Void in
    print("finish GCD \(Thread.current)")
}
var testBlock1 = { () -> Void in
    print("block 1 in \(Thread.current)")
}
var testBlock2 = { () -> Void in
    print("block 2 in \(Thread.current)")
}
var testBlock3 = { () -> Void in
    print("block 3 in \(Thread.current)")
}

var testBlocks = Array<() -> Void>()
testBlocks.append(contentsOf: [testBlock1, testBlock2, testBlock3])

// add group task to queue
for block in testBlocks {
    //let workItem = DispatchWorkItem(block: block)
    //queue.async(group: group, execute: workItem)
    concurrentQueue.async(group: group, execute: block)
}
// when group finished, hook up lastBlockGCD
group.notify(queue: concurrentQueue, execute: lastBlockGCD)

GCD 进程通信

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
    // 图片的网络路径
    NSURL*url = [NSURLURLWithString:
    @"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"\];

    // 加载图片
    NSData*data = [NSDatadataWithContentsOfURL:url];
    // 生成图片
    UIImage*image = [UIImageimageWithData:data];
    // 回到主线程
    dispatch_async(dispatch_get_main_queue(), ^{
        self.imageView.image = image;
    });
});
func updateImageView(urlString: String, imageView: UIImageView?) {
    guard let imageView = imageView,
        let url = URL(string: urlString) else {
            return
    }
    DispatchQueue.global().async {

        if  let data = try? Data(contentsOf: url),
            let image = UIImage(data: data) {

            DispatchQueue.main.async {
                imageView.image = image
            }
        }
    }
}

DispatchQueue.once {}

from http://www.jianshu.com/p/640b64faea9a

public extension DispatchQueue {

    private static var _onceTracker = [String]()

    /**
     Executes a block of code, associated with a unique token, only once.  The code is thread safe and will
     only execute the code once even in the presence of multithreaded calls.

     - parameter token: A unique reverse DNS style name such as com.vectorform.<name> or a GUID
     - parameter block: Block to execute once
     */
    public class func once(token: String, block:()->Void) {
        // add sync lock
        objc_sync_enter(self)
        defer { objc_sync_exit(self) }

        if _onceTracker.contains(token) {
            return
        }

        _onceTracker.append(token)
        block()
    }
}


DispatchQueue.once(token: "com.vectorform.test") {
    print( "Do This Once!" )
}

private let _onceToken = NSUUID().uuidString

DispatchQueue.once(token: _onceToken) {
    print( "Do This Once!" )
}

results matching ""

    No results matching ""