美文网首页
使用Serial queue处理并发任务

使用Serial queue处理并发任务

作者: 玉米地里种玉米 | 来源:发表于2019-03-14 13:59 被阅读0次

现如今,几乎我们的app都需要和服务端进行网络通信。但是,如果我们像处理用户交互一样处理网络通信,整个UI就很容易被卡住

对于每一个app来说,都有一个主线程用来处理界面更新、响应用户交互等事件,这些事件发生时,它们就会被放到一个由主线程处理的事件队列里由主线程按照发生的顺序依次处理它们。
当主线程进行下载图片(或者进行耗时操作的时候)处理时候,其他的UI交互事件只能暂时等在队列里。因此,这个时候UI是没有响应的。而当下载进行完成后,主线程发现还有一个UI拖动的事件,这时,他就会把处理UI移动到相应的位置。

当然,这种体验是非常糟糕的,因此,我们不要把任何网络IO的代码放到一个app的主线程中队列执行:

创建并使用额外的Serial Queue

一个serial queue和主线程使用的队列是非常类似的:

  • 它们都只能顺序执行队列中的任务;
  • 主线程队列可以和多个serial queue并行执行

因此,我们只要新创建一个serial queue,然后在进行耗时任务时,把耗时任务放进去就可以了。我们使用下面的方式创建一个自己的serial queue:

// Create a serial queue
let serialQueue = dispatch_queue_create("serial queue name", DISPATCH_QUEUE_SERIAL)

创建好之后,我们使用dispatch_async,把任务添加到serial queue

dispatch_async(serialQueue, {
    let img1 = Downloader.downloadImageWithURL(self.imageUrls[0])
    // 所有更新UI的操作,必须在主线程中完成 
    // 我们使用dispatch_get_main_queue获得主线程队列
    dispatch_async(dispatch_get_main_queue(), {
        self.image1.image = img1
        self.image1.clipsToBounds = true
    })
})

dispatch_async的第一个参数是要插入的队列,第二个参数是一个()->Void类型的closure,表示要插入到队列的任务。

使用多个serial queue

我们还可以把图片放在不同的serial queue里下载,这样,虽然在一个serial queue内部任务是串行执行的,但多个serial queue之间,是并行执行的。

// Add task
let serialQueue1 = 
    dispatch_queue_create("name", 
    DISPATCH_QUEUE_SERIAL)
dispatch_async(serialQueue1, {
    let img1 = 
        Downloader.downloadImageWithURL(self.imageUrls[0])

    dispatch_async(dispatch_get_main_queue(), {
        self.image1.image = img1
        self.image1.clipsToBounds = true
    })
    // Omit for simplicity...
})

let serialQueue2 = 
    dispatch_queue_create("name1", 
    DISPATCH_QUEUE_SERIAL)
dispatch_async(serialQueue2, {
    let img2 = 
        Downloader.downloadImageWithURL(self.imageUrls[1])
    dispatch_async(dispatch_get_main_queue(), {
        self.image2.image = img2
        self.image2.clipsToBounds = true
    })
    // Omit for simplicity...
})

我们向大家介绍了通过serial queue和主线程并行执行任务以及在主线程中更新UI的方法。

我们介绍了serial,在iOS中叫做Grand Central Dispatch,它是一组相对低层的C语言API。尽管GCD对线程管理进行了封装,如果我们要管理队列中的任务(例如:查看任务状态、取消任务、控制任务之间的执行顺序等)仍然不是很方便。

相关文章

  • 使用Serial queue处理并发任务

    现如今,几乎我们的app都需要和服务端进行网络通信。但是,如果我们像处理用户交互一样处理网络通信,整个UI就很容易...

  • GCD

    队列的两种类型:并发() 串行(Serial Dispatch Queue) 串行队列:一次只调度一个任务,队列...

  • GCD

    Dispatch Queue的种类 Serial Dispatch Queue 等待现在执行中处理结束 (按照追加...

  • 多线程-GCD

    Dispatch Queues Serial Dispatch Queue单线程模式,一个任务处理完才会执行下一个...

  • iOS面试8 - 多线程

    GCD 同步异步, 串行并发同步串行: dispatch_sync(serial_queue, ^{ // wor...

  • 第三章 3.2.6 Dispatch Group

    问题一、在追加到Dispatch Queue中的多个处理全部结束后想执行结束处理?1、使用一个Serial Dis...

  • GCD串行队列与并发队列

    GCD的队列可以分为2大类型:串行队列、并发队列。一: 串行队列(Serial Dispatch Queue):一...

  • Dispatch Queue

    queue types Serial Concurrent Main dispatch queue Queue-R...

  • iOS开发—GCD笔记

    多线程,主GCD 串行队列(Serial Dispatch Queue,等待现有处理结束) 并行队列�(Concu...

  • 《Objective-C 高级编程》GCD 笔记摘要

    GCD 的 API Dispatch Queue 串行(Serial):任务按顺序执行,一次只能执行一个任务,只有...

网友评论

      本文标题:使用Serial queue处理并发任务

      本文链接:https://www.haomeiwen.com/subject/odmqmqtx.html