Swift   发布时间:2022-03-31  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Swift多线程:GCD进阶,单例、信号量、任务组大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

其实这个标题不知道怎么写了,都很碎,也没有想到特别合适的例子能够全部放在一起的。索性就这么平铺开吧。 1 dispatch_once,以及Swift下的单例 使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次。所以在通常在OC时代,我们都会用它来写单例。 但是,但是,但是:这个函数在Swift3.0以后的时代已经被删除了。没错,被删除了,不用了。 原来自从Swift 1.

其实这个标题不知道怎么写了,都很碎,也没有想到特别合适的例子能够全部放在一起的。索性就这么平铺开吧。


Swift多线程:GCD进阶,单例、信号量、任务组


1
dispatch_once,以及Swift下的单例


使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次。所以在通常在OC时代,我们都会用它来写单例。


但是,但是,但是:这个函数在Swift3.0以后的时代已经被删除了。没错,被删除了,不用了。


原来自从Swift 1.x开始Swift就已经开始用dispatch_one机制在后台支持线程安全的全局lazy初始化和静态属性。static var背后已经在使用dispatch_once了,所以从Swift 3开始,就干脆把dispatch_once显式的取消了。


凸(艹皿艹 ),那Swift里面的单例怎么写呐?其实方法有很多种,有OC心Swift皮的写法、新瓶装老酒的写法,那既然咱们开始了Swift,就抛下过去那写沉重包袱吧。这里非典型技术宅只分享其中的一种。



什么?你在搞事情吧,就这么点?是的,因为是全局变量,所以只会创建一次。


  • 使用final,将这个单例类终止继承。

  • 设置初始化方法为私有,避免外部对象通过访问init方法创建单例类的实例。


2
dispatch_after


在GCD中我们使用dispatch_after()函数来延迟执行队列中的任务。准确的理解是,等到指定的时间到了以后,才会开辟一个新的线程然后立即执行队列中的任务。


所以dispatch_after不会阻塞当前任务,并不是先把任务加到线程里面,等时间到了在执行。而是等时间了,才加入到线程中。


我们使用两种时间格式来看看。


方法一:使用相对时间,DispatchTime



方法二:使用绝对时间,DispatchWallTime



3
队列的循环、挂起、恢复


3.1 dispatch_apply


dispatch_apply函数是用来循环来执行队列中的任务的。在Swift 3.0里面对这个做了一些优化,使用以下方法



本来循环执行就是为了节约时间的嘛,所以认就是用了并行队列。我们尝试一下用这个升级版的dispatch_apply让它执行10次打印任务。



运行结果如下:


@H_606_403@


看,是不是所有的任务都是并行进行的?标红的地方,是非典型技术宅想提醒一下大家这里还是有一些任务是在主线程中进行的。它循环执行并行队列中的任务时,会开辟新的线程,不过有可能会在当前线程中执行一些任务。


如果需要循环的任务里面有特别耗时的操作,我们上一篇文章里面说是应该放在global里面的。如何避免在主线程操作这个呐???



3.2 队列的挂起与唤醒


如果一大堆任务执行着的时候,突然后面的任务不想执行的。那怎么办呐?我们可以让它暂时先挂起,等想好了再让它们运行起来。


不过挂起是不会暂停正在执行的队列的哈,只能是挂起还没执行的队列。



Swift多线程:GCD进阶,单例、信号量、任务组


我们也可以看一下控制条的打印结果。显然能看到代码并没有按照顺序执行,新建的queue里面的打印是在被唤醒之后才执行的。


4
信号量(semaphorE)


信号量这个东西在之前的文章里面有一个例子里面用到了,当时还有人专门问我semaphore是什么东西。现在可以好好说一说这个了。


不要问我是哪个例子里面用到了,实在想不起来了呀,只能记得有人问过semaphore这个。


有时候多个线程对一个数据进行操作的时候,会造成一些意想不到的效果。多个人同时对同一个数据进行操作,谁知道怎么搞啊!


为了保证同时只有一个线程来修改这个数据,这个时候我们就要用到信号量了。当信号量为0的时候,其他线程想要修改或者使用这个数据就必须要等待了,等待多久呐?DispatchTime.distantFuture,要等待这么久。意思就是一直等待下去。。。。OC里面管这个叫做DISPATCH_TIME_FOREVER。


如果给信号量设置成了0,其实就意味着这个资源没有人能够再能用了。所以,当用完了之后一定要把信号量设置成非0( ⊙ o ⊙ )!



4.1 简单实用一下


我们简单的让globalQueue这个全局队列按照1->5的顺序进行打印,打印一次休息1秒钟。



看一下打印结果:


Swift多线程:GCD进阶,单例、信号量、任务组


globalQueue 如果不加信号量,正常打印是什么样子的?如果不记得,请看上一篇文章iOS多线程系列之三:使用GCD实现异步下载图片



4.2 多个线程之间进行任务协调


实际工作中,很多时候我们需要在多个任务之间进行协调,每个任务都是多线程的。


打个比方,我们在后台下载音乐、专辑的封面。等着两个都做完了,才通知用户可以去听音乐了。两个任务都是多线程,我们其实并不知道什么时候才能执行完毕。这个时候,就可以靠信号量,让大家互相等待。


为了更简化这个过程,例子里面模拟了一个在另外一个方法中需要耗时1秒的一个操作。当完成之后,才执行后续操作。




5
任务组


GCD的任务组在开发中是经常被使用到,当需要一组任务结束后再执行一些操作时,就可以用它啦。


DispatchGroup的职责就是当队列中的所有任务都执行完毕后,会发出一个通知来告诉告诉大家,任务组中所执行的队列中的任务执行完毕了。


既然是组,里面就肯定有很多队列啦,不然怎么能叫做“组”呐。


队列和组关联有两种方式:手动、自动


5.1 自动关联


肯定先从自动开始了,因为通常自动最省事啊。这还用问嘛。



看看打印结果:


Swift多线程:GCD进阶,单例、信号量、任务组


5.2 手动关联


接下来我们将手动的管理任务组与队列中的关系。


enter(),leave()是一对儿。前者表示进入到任务组。后者表示离开任务组。



Swift多线程:GCD进阶,单例、信号量、任务组


利用任务组可以完成很多场景的工作。例如多任务执行完后,统一刷新UI。把刷新UI的操作放在Notify里面就好了。


还记得刷新UI用哪个queue嘛?hoho~



Swift多线程:GCD进阶,单例、信号量、任务组

(或点击阅读原文,直达CocoaChina商城)


一周精选
@H_891_675@

TIOBE 8 月编程语言排行榜:“后院”硝烟四起

程序员们证明智商的时候到了!一大波智力面试题正在靠近~

项目经理还是CTO?程序猿今后该怎么走?

iOS应用内跳转到系统设置页面

iOS进阶:Objective-C底层原理

公司开发者账号申请(2017最新版)

@H_254_696@

CocoaChina

全球最大苹果开发中文社区

@H_772_717@

Swift多线程:GCD进阶,单例、信号量、任务组

大佬总结

以上是大佬教程为你收集整理的Swift多线程:GCD进阶,单例、信号量、任务组全部内容,希望文章能够帮你解决Swift多线程:GCD进阶,单例、信号量、任务组所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。