https://www.jianshu.com/p/fc78dab5736f
在学习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的更多相关文章
- [转]https://www.jianshu.com/p/06443248f4d8
		eos是什么? 原文 https://www.jianshu.com/p/06443248f4d8 简介 用一句话来定义eos,即:区块链操作系统,支持在它之上构建dapp,支持智能合约.帐户.身份验 ... 
- Zabbix调优不完全指南(https://www.jianshu.com/p/2d911d55448f)
		从学习搭建zabbix到完成各类监控.调优.二次开发已经过去了两年,期间通过QQ学习群.zabbix官方社区.各个技术博客整理学习了不少关于各种报错的处理方法,现在将常见的一些报错处理方法整理出来分享 ... 
- 接口测试之——Charles抓包及常见问题解决(转载自https://www.jianshu.com/p/831c0114179f)
		简介 Charles其实是一款代理服务器,通过成为电脑或者浏览器的代理,然后截取请求和请求结果达到分析抓包的目的.该软件是用Java写的,能够在Windows,Mac,Linux上使用,安装Charl ... 
- jar与war包区别,转自https://www.jianshu.com/p/3b5c45e8e5bd
		https://www.jianshu.com/p/3b5c45e8e5bd 
- fastdfs(https://www.jianshu.com/p/1c71ae024e5e)
		参考 官方网站:https://github.com/happyfish100/ 配置文档:https://github.com/happyfish100/fastdfs/wiki/ 参考资料:htt ... 
- https://www.jianshu.com/p/1038c6170775
		import os # 方法一: os.walk实现 def items_dir(rootname): l = [] for main_dir, dirs, file_name_list in os. ... 
- Redis 单线程却能支撑高并发 - 简书 https://www.jianshu.com/p/2d293482f272
		小结: 1.在 I/O 多路复用模型中,最重要的函数调用就是 select,该方法的能够同时监控多个文件描述符的可读可写情况:2.Redis 服务采用 Reactor 的方式来实现文件事件处理器(每一 ... 
- 当我写下Map<String,Object> map = new HashMap<>() https://www.jianshu.com/p/6b2e350e99be
		当我写下Map<String,Object> map = new HashMap<>();我到底在写什么? 我什么时候会写HashMap? 一个函数同时需要返回 多种 状态的情 ... 
- Asp.Net Core 第01局:项目创建和部署 转载https://www.jianshu.com/p/9c9750e23b3e
		总目录 一.前言 本文通过从项目创建到部署,简单介绍Asp.Net Core. 二.环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 三.开局 第一手:创建项目 ... 
随机推荐
- windowsService 程序
			using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ... 
- 【LOJ2540】「PKUWC2018」随机算法
			题意 题面 给一个 \(n\) 个点 \(m\) 条边的无向图.考虑如下求独立集的随机算法:随机一个排列并按顺序加点.如果当前点能加入独立集就加入,否则不加入.求该算法能求出最大独立集的概率. \(n ... 
- 实验吧-杂项-WTF?(python 01代码转图片)
			比较新的题型了吧. code为base64码,转码出来是01代码,直接蒙圈,查阅相关wp才知道是转图片的. 复制到编辑器里可以看到一共65536个数字,开方是256,于是这就是一个方形的图片了–> ... 
- 搜索await page.waitForSelector(allResultsSelector);
			/** * Copyright 2017 Google Inc. All rights reserved. * * Licensed under the Apache License, Version ... 
- 十 Servlet
			5 web资源: 在http协议当中,规定了请求和响应双方,客户端和服务器.与web相关的资源. 静态资源: html.css.css动态资源: Servlet/jsp ... 
- other#nginx配置
			#user nobody; worker_processes ; #error_log logs/error.log; #error_log logs/error.log notice; #error ... 
- LabVIEW面向对象的ActorFramework(1)
			本系列文章主要阐述以下几个问题: (1)什么是面向对象编程? (2)为什么要学习面向编程? (3)LabVIEW面向编程学习为什么有点难? (4)LabVIEW面向对象的编程架构:Actor Fram ... 
- DOM基础2——元素
			1.造元素 document.createElement("标签名") 例:var div_new=document.createElement("div"); ... 
- JAVA Random 详解
			Java中存在着两种Random函数: 一.java.lang.Math.Random; 调用这个Math.Random()函数能够返回带正号的double值,该值大于等于0.0且小于1.0,即取值范 ... 
- GDI4
			前几篇我已经向大家介绍了如何使用GDI+来绘图,并做了一个截图的实例,这篇我向大家介绍下如何来做一个类似windows画图的工具.个人认为如果想做一个功能强大的绘图工具,那么单纯掌握GDI还远远不够, ... 
