当前位置:主页 > 365bet赔率体系 >

13 GCD应用场景

时间:2019-02-20 00:50 作者:365bet在线开户
标题:13 GCD应用场景
作者丨谔确定
https://juejin.im/post/5a38c19c6fb9a0450809c77c
在本文中,我们不涉及GCD的概念和理论。我们将仅在一些开发方案中介绍GCD应用程序。
欢迎大家添加消息。
耗时的操作
这是最常用的方案。为了避免将操作后的主线程阻塞使用该处理结果在主线程需要时间次级线程(读取一些数据沙箱中,在子进程的界面中显示的数据显示器)。用户此场景中有几个细分。
执行耗时操作后的主线程回调
//主线程需要处理子线程的结果
(SomethingLong:@escaping() - > T,退出:@escaping(T) - >()){
globalQueue.async{
我们说data = somethingLong()。
Self.mainQueue.async{
浇筑(数据)
}
}
}
//主线程不需要处理辅助线程的结果
函数句柄(somethingLong:@escaping() - >(),finshed:@escaping() - >
WorkItem = DispatchWorkItem{等等。
东西长()
}
globalQueue.async(执行:workItem)
workItem.wait()
纠结()
}
/////////////////////////////////////////////////////////////////////////////////////////////////
GCDKit()句柄(somethingLong:{[弱自我]
汽车.Color = UIColor.red
睡觉(2)
{中[弱]
自.View.backgroundColor = self。颜色
}
GCDKit()句柄(somethingLong:{
设p = Person()
P.age = 40
打印(日期(),页面)
睡觉(2)
在回家的路上
{(P:人)in
打印(日期(),页面)
}
耗时的系列操作
每个子任务取决于前一个任务的完成,主线程在完成后回调。
//
待机功能(代码:@escaping GCDKitHandleBlock) - > GCDKit{
handleBlockArr.append(代码)
回报
}
///已处理的回调,主线程中的异步执行
功能结束(代码:@escaping GCDKitHandleBlock){
globalQueue.async{
ForworkItem inself.handleBlockArr{
workItem()
}
self.handleBlockArr.removeAll()
Self.mainQueue.async{
代码()
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
等待GCDKit(){
Self.num + = 1
等等{
Self.num + = 2
等等{
Self.num + = 3
等等{
Self.num + = 4
等等{
Self.num + = 5
{}
打印(self.num,Thread.current)
}
耗时的同时操作
每个子任务都是独立的,所有子任务在完成后都会被调用到主线程中。
//
函数驱动程序(代码:@escaping GCDKitHandleBlock) - > GCDKit{
queue = DispatchQueue(label:“”“,attributes:.concurrent)。
WorkItem = DispatchWorkItem{等等。
代码()
}
Queue.async(group:group,execution:workItem)
回报
}
//此任务将在运行时排除其他并发任务。它通常用于编写事务以确保线程安全性。
FUNC barrierHandle(代码:@escaping GCDKitHandleBlock) - > GCDKit{
queue = DispatchQueue(label:“”“,attributes:.concurrent)。
workItem = DispatchWorkItem(flags:.barrier){等等。
代码()
}
Queue.async(group:group,execution:workItem)
回报
}
///已处理的回调,主线程中的异步执行
Func allDone(代码:@escaping GCDKitHandleBlock){
Group.notify(队列:主要,执行:{
代码()

}
/////////////////////////////////////////////////////////////////////////////////////////////////
GCDKit()
Self.num + = 1
.barrierHandle{
Self.num + = 2
.barrierHandle{
Self.num + = 3
处理{
Self.num + = 4
处理{
Self.num + = 5
.allDone{
Self.num + = 6
打印(self.num,Thread.current)
}
延迟执行
执行代码一段时间后,通常会在打开应用程序一段时间后看到显示注释对话框。
函数函数(when:DispatchTime,代码:@escaping GCDKitHandleBlock){
DispatchQueue.main.asyncAfter(截止日期:)
代码()
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
执行GCDKit()(当:.now()+。秒(120)){
auto.something()
}
计时器 定时器的目标是一个重要的参考资料,因此需要特殊处理才能丢弃定时器。Timer的操作取决于Runloop。在Runloop循环,因为计时器不会只执行一次,所以是Runloop变得更重的可能性,让计时器的执行,当您使用定时器,你也可以使用CGD TimerSource。
计时器
//
/// - 参数:
/ / / - 开始:开始时间
/ / / - 结束:结束时间
/ / / - 重复:频率重复
/ / / - 操作空间:容差错误 / / / - eventHandle:处理事件
/// - cancelHandle:计时器结束事件
功能定时器(开始:DispatchTime,
结束:DispatchTime,
重复:双,
Leeway:DispatchTimeInterval,
eventHandle:@转义GCDKitHandleBlock,
cancelHandle:GCDKitHandleBlock=零)
{
Timer = DispatchSource.makeTimerSource()。
timer.setEventHandler{
eventHandle()
}
timer.setCancelHandler{
cancelHandle()
}
Timer.schedule(截止日期:开始,重复:重复,操作边际:操作边际)
Timer.resume()
执行(时:最终){
Timer.cancel()
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
GCDKit()计时器(开始:.now(),
结束:.now()+。秒(10)
重复:2,
余地。毫秒(1),
eventHandle:{
auto.something()
}){)
打印(“取消计时器”)
平行路线
如果需要更快地处理数据,可以使用并发格式同时执行循环操作。
功能图< T>(数据:[T],??代码:(T) - >()){
DispatchQueue.concurrentPerform(iterations:data.count){(i)in
代码(data[i])
}
}
函数代码(代码:(Int) - >(),repeat:Int){
DispatchQueue.concurrentPerform(迭代:迭代){(i)in
代码(i)
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
数据=[1,2,3]。
Var sum = 0
映射GCDKit()(数据:数据){(ele:Int)
睡觉(1)
总和+ = ele
}
印刷(总计)
执行GCDKit()(代码:{(i)in
睡觉(1)
Sum + = data[i]
重复:data.count)
印刷(总计)
控制并发
您可能需要同时处理多个任务,但您可能不希望同时打开多个线程。GCD中没有最大并发概念NSOperation,但它可以用交通信号灯实现。
DoSomething函数(标签:字符串,成本:UInt32,完成:@escaping() - >()){
NSLog(“启动任务%@”,标签)
睡眠(费用)
NSLog(“结束任务%@”,标签)
完成()
}
/////////////////////////////////////////////////////////////////////////////////////////////////
信号量= DispatchSemaphore(值:3)
queue = DispatchQueue(label:“”,qos:.default,attributes:.concurrent)。
Queue.async{
Semaphore.wait()
自动的东西(标签:“1”,费用:2,满:{
打印(Thread.current)
Semaphore.signal()

}
Queue.async{
Semaphore.wait()
自动的东西(标签:“2”,费用:2,满:{
打印(Thread.current)
Semaphore.signal()

}
Queue.async{
Semaphore.wait()
自动的东西(标签:“3”,费用:4,满:{
打印(Thread.current)
Semaphore.signal()

}
Queue.async{
Semaphore.wait()
自动的东西(标签:“4”,费用:2,满:{
打印(Thread.current)
Semaphore.signal()

}
Queue.async{
Semaphore.wait()
自动的东西(标签:“5”,费用:3,满:{
打印(Thread.current)
Semaphore.signal()

}
时间管理
时间管理有几种组合。
在子任务中打开一个线程。 ?子任务按顺序执行。 不要按顺序打开子任务中的线程。
请参阅耗时的操作部分。
按顺序运行子任务中的线程。
通常,在网络请求中,接口的请求参数是另一个接口的返回值。在这种情况下,必须每小时管理网络请求。以下代码显示了网络请求的封装。
funcnetworkTask(tag:string,cost:UInt32,complete:@escaping() - >()){
NSLog(“StartnetworkTasktask%@”,标签)
DispatchQueue.global()。异步{
睡眠(费用)
NSLog(“EndnetworkTasktask%@”,标签)
DispatchQueue.main.async{
完成()
}
}
}
如果可以链接辅助子进程,则需要进行顺序执行的信号控制。
Group = DispatchGroup()。
Group.enter()
networkTask(tag:“1”,cost:2,full:{
Group.leave() )
Group.enter()
networkTask(tag:“2”,cost:4,full:{
Group.leave()

Group.enter()
networkTask(tag:“3”,cost:2,full:{
Group.leave()

Group.enter()
networkTask(tag:“4”,cost:4,full:{
Group.leave()

Group.notify(队列:主要,执行:{
打印(“创建整个网络”)

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////
2017-12-19 14:10:3?? ?? 3.876393 + 0800演示[16495:4973791]启动网络任务1
2017-12-19 14:10:3?? ?? 3.878869 + 0800演示[16495:4973791]启动网络任务2任务2 二○一七年十二月一十九日14:10:3 ?? 3.879142 + 0800演示[16495:4973791]的网络任务tarea3的开始
2017-12-19 14:10:3?? ?? 3.879309 + 0800演示[16495:4973791]启动网络任务4
二○一七年十二月一十九日14:10:3 ?? 5.883851 + 0800演示[16495:4974025]的网络任务TASK1的端
二○一七年十二月一十九日14:10:3 ?? 5.883850 + 0800演示[16495:4974030]的网络利亚tarea3的端
演示3 ?? 7.883995 + 0800:网络结束任务2的[16495:4974026]2017年12月19日14:10
二○一七年十二月一十九日14:10:3 ?? 7.883995 + 0800演示[16495:4974027]结束任务的redTarea4
完成整个网络
//你可以像这样省略它
我想要downloadGroup = DispatchGroup()。
执行GCDKit()(代码:{(i)in
downloadGroup.enter()
networkTask(tag:“(i)”,cost:UInt32(i),full:{
downloadGroup.leave()

重复:10)
downloadGroup.notify(queue:main){
打印(“创建整个网络”)
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////
2017-12-1915:07:13.253428 + 0800演示[49319:5169745]网络任务tarea3开始
2017-12-1915:07:13.253428 + 0800演示[49319:5169743]的网络的起始任务2
2017-12-1915:07:13.253428 + 0800演示[49319:5169744]启动网络任务任务0
2017-12-1915:07:13.253479 + 0800演示[49319:5169474]启动网络任务1
2017-12-1915:07:13.253946 + 0800演示[49319:5169744]的网络6的任务的开始
2017-12-1915:07:13.253947 + 0800演示[49319:5169743]的网络的起始任务4
2017-12-1915:07:13.253947 + 0800演示[49319:5169745]启动网络任务5
2017-12-1915:07:13.254119 + 0800演示[49319:5169763]红色任务0任务结束
2017-12-1915:07:13.254193 + 0800演示[49319:5169474]的网络任务开始72017-12-1915:07:13.254339 + 0800演示[49319:5169744]的网络任务开始8
2017-12-1915:07:13.254343 + 0800演示[49319:5169743]启动网络任务9
2017-12-1915:07:14.258061 + 0800演示[49319:5169764]网络终端区域任务1
2017-12-1915:07:15.258071 + 0800演示[49319:5169762]网络任务结束2
2017-12-1915:07:16.258189 + 0800演示[49319:5169742]的网络利亚tarea3的端
2017-12-1915:07:17.258100 + 0800演示[49319:5169745]Red Tarea 4任务结束
2017-12-1915:07:18.258196 + 0800演示[49319:5169766]任务redTareas5的端
2017-12-1915:07:19.258171 + 0800演示[49319:5169765]的网络的末端任务6
2017-12-1915:07:20.259119 + 0800演示[49319:5169763]网络任务结束7
2017-12-1915:07:21.258239 + 0800演示[49319:5169767]任务redTareas8的端
2017-12-1915:07:22.258280 + 0800演示[49319:5169744]红色Tareas 9任务结束
整个网络完成。
子任务中的开放线程不会按顺序执行
这种情况需要多个接口,毕竟请求已经完成时,必须执行某些操作,变得更加普遍。这可以由GCD任务组处理。
Group = DispatchGroup()。
Group.enter()
networkTask(tag:“1”,cost:2,full:{
Group.leave()

Group.enter()
networkTask(tag:“2”,cost:4,full:{
Group.leave()

Group.enter()
networkTask(tag:“3”,cost:2,full:{
Group.leave()

Group.enter()
networkTask(tag:“4”,cost:4,full:{
Group.leave()

Group.notify(队列:主要,执行:{
打印(“创建整个网络”)

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////
2017-12-19 14:10:3?? ?? 3.876393 + 0800演示[16495:4973791]启动网络任务1
2017-12-19 14:10:3?? ?? 3.878869 + 0800演示[16495:4973791]启动网络任务2任务2
二○一七年十二月一十九日14:10:3 ?? 3.879142 + 0800演示[16495:4973791]的网络任务tarea3的开始
2017-12-19 14:10:3?? ?? 3.879309 + 0800演示[16495:4973791]启动网络任务4
二○一七年十二月一十九日14:10:3 ?? 5.883851 + 0800演示[16495:4974025]的网络任务TASK1的结束 二○一七年十二月一十九日14:10:3 ?? 5.883850 + 0800演示[16495:4974030]的网络利亚tarea3的端
演示3 ?? 7.883995 + 0800:网络结束任务2的[16495:4974026]2017年12月19日14:10
二○一七年十二月一十九日14:10:3 ?? 7.883995 + 0800演示[16495:4974027]结束任务的redTarea4
完成整个网络
//你可以像这样省略它
我想要downloadGroup = DispatchGroup()。
执行GCDKit()(代码:{(i)in
downloadGroup.enter()
networkTask(tag:“(i)”,cost:UInt32(i),full:{
downloadGroup.leave()

重复:10)
downloadGroup.notify(queue:main){
打印(“创建整个网络”)
} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////
2017-12-1915:07:13.253428 + 0800演示[49319:5169745]网络任务tarea3开始
2017-12-1915:07:13.253428 + 0800演示[49319:5169743]的网络的起始任务2
2017-12-1915:07:13.253428 + 0800演示[49319:5169744]启动网络任务任务0
2017-12-1915:07:13.253479 + 0800演示[49319:5169474]启动网络任务1
2017-12-1915:07:13.253946 + 0800演示[49319:5169744]的网络6的任务的开始
2017-12-1915:07:13.253947 + 0800演示[49319:5169743]的网络的起始任务4
2017-12-1915:07:13.253947 + 0800演示[49319:5169745]启动网络任务5
2017-12-1915:07:13.254119 + 0800演示[49319:5169763]红色任务0任务结束
2017-12-1915:07:13.254193 + 0800演示[49319:5169474]启动网络任务7
2017-12-1915:07:13.254339 + 0800演示[49319:5169744]启动网络任务8
2017-12-1915:07:13.254343 + 0800演示[49319:5169743]启动网络任务9
2017-12-1915:07:14.258061 + 0800演示[49319:5169764]网络终端区域任务1
2017-12-1915:07:15.258071 + 0800演示[49319:5169762]网络任务结束2
2017-12-1915:07:16.258189 + 0800演示[49319:5169742]的网络利亚tarea3的端
2017-12-1915:07:17.258100 + 0800演示[49319:5169745]Red Tarea 4任务结束
2017-12-1915:07:18.258196 + 0800演示[49319:5169766]任务redTareas5的端
2017-12-1915:07:19.258171 + 0800演示[49319:5169765]的网络的末端任务6
2017-12-1915:07:20.259119 + 0800演示[49319:5169763]网络任务结束7
2017-12-1915:07:21.258239 + 0800演示[49319:5169767]任务redTareas8的端
2017-12-1915:07:22.258280 + 0800演示[49319:5169744]红色Tareas 9任务结束
整个网络完成。
自定义数据监听
如果您需要侦听特定数据的更改,但不需要经常调用相应的回调过程,则可以使用DispatchSourceUserData等待。当队列空闲时,更改和回调会自动合并。CPU
GCDKit扩展{
init(valueChanged:@escaping(T) - >()){
Self.init()
userDataAddSource = DispatchSource.makeUserDataAddSource()
userDataAddSource.setEventHandler(handler:{[weak self]in
守卫让'self` = selfelse{return}
警卫离开值= auto.value else{return}
valueChanged(value)

userDataAddSource.resume()
}
传输函数(_value:T){
自动值=值
userDataAddSource.add(数据:1)
}
}/ ///////////////////////////////////////////////////////////////////////////////////////////////
GCD = GCDKit< Int>{(value:Int)in
印刷(价值)
}
保留serialQueue = DispatchQueue(标签:“com”)
serialQueue.async{
Fori in 1 ... 1000{
self.GCD.send(i)
}
Fori在1000 ... 9999{
self.GCD.send(i)
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
64
9999
听力过程
在Mac开发中,您可以监视其他进程的打开和关闭。
Letapps = NSRunningApplication.runningApplications(使用BundleIdentifier:“com.apple.mail”)
letprocessIdentifier = apps.first.processIdentifier
Letsource = DispatchSource.makeProcessSource(标识符:pid,eventMask:end)
source.setEventHandler{
打印(“停止电子邮件”)
}
Source.resume()
收听目录结构
文件夹=我们试试吧对于FileManager.default.url(对于:.documentDirectory,
在.userDomainMask中,
适合:零,
创建:false)
打印(文件夹!根)
保留fd = open(文件夹!。路径,O_CREAT,0o644)。
make queue = DispatchQueue(label:“m”)。
source = DispatchSource.makeFileSystemObjectSource(fileDeor:fd,依此类推。
eventMask:.all,
可乐:尾巴)
source.setEventHandler{
打印(“更改文件夹”)
}
简历引用()
保留结果= FileManager.default.createFile(atPath:folder!.Path +“/ abc”,content:nil,attribute:nil)
如果结果是{
打印(0)
}
其他{
印刷(1)
}
安全线程 您可以限制正在读取和写入资源的线程,而不使用线程锁定,如下所示:
/// .barrier保证在执行期间排除其他并发任务。这通常用于编写事务和安全线程安全性。
FUNC barrierHandle(代码:@escaping GCDKitHandleBlock) - > GCDKit{
Letqueue = DispatchQueue(标签:“”,属性:.concurrent)
letworkItem = DispatchWorkItem(flags:.barrier){
代码()
}
可乐异步(组:组,执行:workItem)
回报
}
或者,在串行队列上启动同步读/写任务。
GCDKit扩展{
瓦尔达塔:T{
收购{
returnreadWriteQueue.sync{Value}
}
设置{ readWriteQueue.sync{value = newValue}
}
}
}


退房
备注
编辑负责人:

上一篇:AWS通过三种主要产品改变了处理器和服务器市场

下一篇:1月26日生日那天,工作室写了一个晚上庆祝他的