在学习Swift 3的过程中整理了一些笔记,如果想看其他相关文章可前往《Swift 3必看》系列目录

swift 3中对C层级的GCD的API进行了彻头彻尾的改变。本文将从实际使用场景来了解一下新的api使用。

dispatch_async

一个常见的场景就是在一个全局队列进行一些操作后切换到主线程配置UI。现在是这么写:

DispatchQueue.global().async {
// code
DispatchQueue.main.async {
// 主线程中
}
}

global()是一个有着默认参数的静态函数:

class DispatchQueue : DispatchObject {
public class var main: DispatchQueue
public class func global(qos: DispatchQoS.QoSClass = default) -> DispatchQueue
}

sync

如果想同步执行操作,和async类似,调用sync就可以了:

DispatchQueue.global().sync {
// 同步执行
}

优先级:DispatchQoS

我们知道,GCD 的默认队列优先级有四个:

  • DISPATCH_QUEUE_PRIORITY_HIGH
  • DISPATCH_QUEUE_PRIORITY_DEFAULT
  • DISPATCH_QUEUE_PRIORITY_LOW
  • DISPATCH_QUEUE_PRIORITY_BACKGROUND

现在则改为了QoSClass枚举

 public enum QoSClass {

        case background

        case utility

        case `default`

        case userInitiated

        case userInteractive

        case unspecified

        public init?(rawValue: qos_class_t)

        public var rawValue: qos_class_t { get }
}

这些命名比原先的更加友好,能更好表达这个操作的意图。

 
 

和原有的对应关系是:

* DISPATCH_QUEUE_PRIORITY_HIGH:         .userInitiated
* DISPATCH_QUEUE_PRIORITY_DEFAULT: .default
* DISPATCH_QUEUE_PRIORITY_LOW: .utility
* DISPATCH_QUEUE_PRIORITY_BACKGROUND: .background

创建队列

DispatchQueue的默认初始化方法创建的就是一个同步队列,如果要创建并发的队列,在attributes中声明concurrent。

// 同步队列
let serialQueue = DispatchQueue(label: "queuename") // 并发队列
let concurrentQueue = DispatchQueue(label: "queuename", attributes: .concurrent)

推迟时间后执行

原先的dispatch_time_t现在由DispatchTime对象表示。可以用静态方法now获得当前时间,然后再通过加上一个DispatchTimeInterval枚举来获得一个需要延迟的时间。

let delay = DispatchTime.now() + DispatchTimeInterval.seconds(60)
DispatchQueue.main.asyncAfter(deadline: delay) {
// 延迟执行
}

这里也可以直接加上一个秒数。

let three = DispatchTime.now() + 3.0

因为DispatchTime中自定义了<code>+</code>号。


public func +(time: DispatchTime, seconds: Double) -> DispatchTime

DispatchGroup

如果想在dispatch_queue中所有的任务执行完成后再做某种操作可以使用DispatchGroup。原先的dispatch_group_t由现在的DispatchGroup对象代替。

let group = DispatchGroup()

let queueBook = DispatchQueue(label: "book")
queueBook.async(group: group) {
// 下载图书
}
let queueVideo = DispatchQueue(label: "video")
queueVideo.async(group: group) {
// 下载视频
} group.notify(queue: DispatchQueue.main) {
// 下载完成
}

DispatchGroup会在组里的操作都完成后执行notify。
如果有多个并发队列在一个组里,我们想在这些操作执行完了再继续,调用wait

group.wait()

DispatchWorkItem

使用DispatchWorkItem代替原来的<code>dispatch_block_t</code>。
在DispatchQueue执行操作除了直接传了一个<code>() -> Void</code>类型的闭包外,还可以传入一个DispatchWorkItem。


public func sync(execute workItem: DispatchWorkItem) public func async(execute workItem: DispatchWorkItem)

DispatchWorkItem的初始化方法可以配置Qos和DispatchWorkItemFlags,但是这两个参数都有默认参数,所以也可以只传入一个闭包。

    public init(qos: DispatchQoS = default, flags: DispatchWorkItemFlags = default, block: @escaping @convention(block) () -> ())

let workItem = DispatchWorkItem {
// TODO:
}

DispatchWorkItemFlags枚举中assignCurrentContext表示QoS根据创建时的context决定。
值得一提的是DispatchWorkItem也有wait方法,使用方式和group一样。调用会等待这个workItem执行完。

let myQueue = DispatchQueue(label: "my.queue", attributes: .concurrent)
let workItem = DispatchWorkItem {
sleep(1)
print("done")
}
myQueue.async(execute: workItem)
print("before waiting")
workItem.wait()
print("after waiting")

barrier

假设我们有一个并发的队列用来读写一个数据对象。如果这个队列里的操作是读的,那么可以多个同时进行。如果有写的操作,则必须保证在执行写入操作时,不会有读取操作在执行,必须等待写入完成后才能读取,否则就可能会出现读到的数据不对。在之前我们用dipatch_barrier实现。
现在属性放在了DispatchWorkItemFlags里。

let wirte = DispatchWorkItem(flags: .barrier) {
// write data
}
let dataQueue = DispatchQueue(label: "data", attributes: .concurrent)
dataQueue.async(execute: wirte)

信号量

为了线程安全的统计数量,我们会使用信号量作计数。原来的dispatch_semaphore_t现在用DispatchSemaphore对象表示。
初始化方法只有一个,传入一个Int类型的数。


let semaphore = DispatchSemaphore(value: 5) // 信号量减一
semaphore.wait() //信号量加一
semaphore.signal()

dispatch_once被废弃

在swift 3中已经被废弃了。
简单的建议就是一些初始化场景就用懒加载吧。

// Examples of dispatch_once replacements with global or static constants and variables.
// In all three, the initialiser is called only once. // Static properties (useful for singletons).
class Object {
static let sharedInstance = Object()
} // Global constant.
let constant = Object() // Global variable.
var variable: Object = {
let variable = Object()
variable.doSomething()
return variable
}()

欢迎关注我的微博:@没故事的卓同学

相关链接:
SE0088-Modernize libdispatch for Swift 3 naming conventions
Concurrent Programming With GCD in Swift 3

作者:没故事的卓同学
链接:https://www.jianshu.com/p/fc78dab5736f
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

https://www.jianshu.com/p/fc78dab5736f的更多相关文章

  1. [转]https://www.jianshu.com/p/06443248f4d8

    eos是什么? 原文 https://www.jianshu.com/p/06443248f4d8 简介 用一句话来定义eos,即:区块链操作系统,支持在它之上构建dapp,支持智能合约.帐户.身份验 ...

  2. Zabbix调优不完全指南(https://www.jianshu.com/p/2d911d55448f)

    从学习搭建zabbix到完成各类监控.调优.二次开发已经过去了两年,期间通过QQ学习群.zabbix官方社区.各个技术博客整理学习了不少关于各种报错的处理方法,现在将常见的一些报错处理方法整理出来分享 ...

  3. 接口测试之——Charles抓包及常见问题解决(转载自https://www.jianshu.com/p/831c0114179f)

    简介 Charles其实是一款代理服务器,通过成为电脑或者浏览器的代理,然后截取请求和请求结果达到分析抓包的目的.该软件是用Java写的,能够在Windows,Mac,Linux上使用,安装Charl ...

  4. jar与war包区别,转自https://www.jianshu.com/p/3b5c45e8e5bd

    https://www.jianshu.com/p/3b5c45e8e5bd

  5. fastdfs(https://www.jianshu.com/p/1c71ae024e5e)

    参考 官方网站:https://github.com/happyfish100/ 配置文档:https://github.com/happyfish100/fastdfs/wiki/ 参考资料:htt ...

  6. https://www.jianshu.com/p/1038c6170775

    import os # 方法一: os.walk实现 def items_dir(rootname): l = [] for main_dir, dirs, file_name_list in os. ...

  7. Redis 单线程却能支撑高并发 - 简书 https://www.jianshu.com/p/2d293482f272

    小结: 1.在 I/O 多路复用模型中,最重要的函数调用就是 select,该方法的能够同时监控多个文件描述符的可读可写情况:2.Redis 服务采用 Reactor 的方式来实现文件事件处理器(每一 ...

  8. 当我写下Map<String,Object> map = new HashMap<>() https://www.jianshu.com/p/6b2e350e99be

    当我写下Map<String,Object> map = new HashMap<>();我到底在写什么? 我什么时候会写HashMap? 一个函数同时需要返回 多种 状态的情 ...

  9. Asp.Net Core 第01局:项目创建和部署 转载https://www.jianshu.com/p/9c9750e23b3e

    总目录 一.前言 本文通过从项目创建到部署,简单介绍Asp.Net Core. 二.环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 三.开局 第一手:创建项目   ...

随机推荐

  1. arm linux 移植 MQTT (paho、mosquitto)

    前言 我们在这里做2件事情: 1)编译 paho.mqtt.mosquitto 2个开源项目的c版本库(mosquitto库没有用上) 2)编译好 依赖 paho.mqtt的库编写例程 + mosqu ...

  2. 利用 Ruoyi 开发自己的业务管理系统__测试结构完成

    前言铺垫不多说 (1)Ruoyi这个平台不错:如果你觉得你比Ruoyi的作者牛逼,你就不用看我这个文章了,你可以走了,因为我自认为比Ruoyi的作者要烂: (2)必须已经成功搭建Ruoyi,并能在自己 ...

  3. MySQL如何获取时间戳

    时间戳函数:current_timestamp() 将时间列格式设为timestamp,设定其默认值为CURRENT_TIMESTAMP. 插入一条新纪录,数据库就会自动在时间列存储当前时间.

  4. NIO三大组件简介

    NIO简介 NIO 是面向缓冲区(或者说面向块)编程的, 因为Buffer底层本质上就是内存块.数据被读取到一个缓冲区, 稍后再被它处理, 需要时数据可在缓冲区前后移动, 从而增加了处理过程中的灵活性 ...

  5. Arrays类常用方法

    Arrays类 3.1 概述 java.util.Arrays 此类包含用来操作数组的各种方法,比如排序和搜索等.其所有方法均为静态方法. 3.2 操作数组的方法 1.将参数数组变成字符串 publi ...

  6. JuJu团队12月3号工作汇报

    JuJu团队12月3号工作汇报 JuJu   Scrum 团队成员 今日工作 剩余任务 困难 于达 修改batch里给sentence加padding的方法 继续调试 无 婷婷 给crossentro ...

  7. 【剑指Offer】面试题32 - II. 从上到下打印二叉树 II

    题目 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行. 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回 ...

  8. node核心 http模块

    node作为服务器更多的是web服务器 1.http模块 首先:http是一个协议.里面有通信机制,状态码一大堆乱七八糟的东西.自己写猴年马月都写不出来,这个对象帮我们集成.直接用 服务器对象: ht ...

  9. Spring入门之五-------SpringIoC之通过注解实现

    一.准备工作 创建一个Class注解@Configuration,如下例子: @Configuration // 该注解可理解为将当前class等同于一个xml文件 @ComponentScan(&q ...

  10. golang 读取 chrome保存的网站账号信息

    package main import ( "database/sql" "fmt" "log" "os" " ...