为什么要用GCD-Swift2.x
为什么要用GCD-Swift2.x当今世界,多核已然普及。但是APP却不见得很好的跟上了这个趋势。APP 你并不是一定要写一个大并发的APP才需要用GCD。使用GCD可以让你的APP更快的 线程传统的多任务分发方式是使用线程。在一个多核的设备上,每一个新的线程都可以被分配在一个CPU核心 单核心的CPU麻烦一些,系统会不停地在几个线程之间切换以保证每个线程都有机会执行。这样做的效果 是看起来像是并行执行的,但是其实多个线程的不同任务之间是顺序执行的。 但是使用线程也会遇到一个很大的问题。数据在线程之间的正确传递就是一个很大的难题了。线程之间的 同步当你有多个线程在执行的时候,你一般都会遇到一个问题Race Condition,实际的运算结果 class BankAccount {
var balance: Double?
//...
}
// 创建一个账号,给这个账号存100块
var account = BankAccount()
account.balance = 100
// 第一个线程:取10块
func withdraw() {
let balance = account.balance
account.balance = balance! - 10
}
// 第二个线程:增加10%的利息
func accrue() {
let balance = account.balance
account.balance = balance! * 1.10
}
// 那么最后:account.balance = ?
最后的结果取决于这两个线程哪一个先执行。在并行的条件下执行的先后顺序是不定的。但是执行顺序不同 上面的代码会有多少个可能的不同结果?balance都会是什么值? Race Condition即使在单核设备下也会发生。
对于这些问题,传统的解决方法如下: 队列GCD把线程的创建、回收以及线程的同步等进一步抽象为队列(Queue)统一管理。 队列,简单而言,就是一个可以让数据按照先进先出的顺序执行。一个APP可以创建多个队列,并且多个 队列比线程有很多的优势。第一,GCD库屏蔽了线程管理的繁琐部分。队列会在需要的时候自动创建线程 总之,队列给你了你线程能给的,但是又不用考虑具体线程的操作。 GCD有三种队列: 系统提供了几种并发队列。这些队列有自己专属的QoS(服务质量种类)。这个服务质量种类是用来表示你提交的
这里需要注意一点,苹果的API也会用到这些全局分发的队列。所以,在这些队列里并不是只有你的任务在执行。当然, Closure队列的任务使用closure封装。 你也可以使用方法加入队列,不过这里只使用block。
这里有一个closure的例子,让你对closure有一个大概的印象。swift的closure就和Objective-C的block func makeIncrementer() -> ((Int) -> Int) { func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(9)
上面的例子 Hello dispatch world!这里需要注意一点:Objective-C的block和Swift的closure。 Closure和block的上下文处理语法基本一样。唯一不同的是变量在closure中直接就是可变的。也就是说Objective-C dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE,0),{ print("hello dispatch:- user interactive") })
dispatch_async(dispatch_get_main_queue(),{ print("hello dispatch:- main queue") })
调用 下面看一个自创队列的例子: @IBAction func concurrentAction(sender: AnyObject) {
let concurrentQueue = dispatch_queue_create("concurrent.test.queue",DISPATCH_QUEUE_CONCURRENT) //1
for i in 0...1000 {
dispatch_async(concurrentQueue){ //2
NSThread.sleepForTimeInterval(1) //3
print("print concurrent queue:- (i)") //4
}
}
}
这里一步一步的介绍一下: dispatch_async(concurrentQueue,{ //2
NSThread.sleepForTimeInterval(1) //3
print("print concurrent queue:- (i)")
})
Barriers很多人看到这里就会想,并发队列在哪儿体现出来队列的概念了呢?这分明就是一个把一堆closure扔进去分开执行的堆或者Set(集合) 目前来看是的,但是当你遇到 我们来看看具体的例子: let concurrentQueue = dispatch_queue_create("concurrent.test.queue",DISPATCH_QUEUE_CONCURRENT)
var count: Int = 0
for _ in 0...100 {
dispatch_async(concurrentQueue){
NSThread.sleepForTimeInterval(1)
print("print concurrent queue:- (count++)")
}
}
dispatch_barrier_async(concurrentQueue,{
print("##ASYNC in barrier,concurrent queue - START")
for _ in 1...10 {
NSThread.sleepForTimeInterval(0.5)
}
print("##ASYNC in barrier,concurrent queue - END")
})
for _ in 0...100 {
dispatch_async(concurrentQueue){
NSThread.sleepForTimeInterval(1)
print("print concurrent queue:- (count++)")
}
}
dispatch_barrier_sync(concurrentQueue,{
print("##SYNC in barrier,concurrent queue - START")
for _ in 1...10 {
NSThread.sleepForTimeInterval(0.5)
}
print("##SYNC in barrier,concurrent queue - END")
})
for _ in 0...100 {
dispatch_async(concurrentQueue){
NSThread.sleepForTimeInterval(1)
print("print concurrent queue:- (count++)")
}
}
注意 读写锁先看一个新闻累的单例的例子。这个例子的最初形态中不是一个线程安全的单例: class NewsFeed {
static let sharedInstance = NewsFeed() //1
private init() {} //2
private var _news: [String] = []
var news: [String] {
return _news
}
func addNews(n: String) {
_news.append(n)
}
}
有这么一个新闻的类。 用户可以调用 解决办法就是任何的线程要添加新闻,那么就必须通过barrier这一道关口。在添加新闻的时候只有一个closure执行。 为了保证线程的安全,读取新闻的操作也只能在 但是使用dispatch sync需要很小心。如前所述,如果你给dispatch sync分配的队列是当前正在运行的队列 private var _news: [String] = []
var news: [String] {
var newsCopy: [String]!
dispatch_sync(concurrentQueue){ //1
newsCopy = self._news //2
}
return newsCopy
}
下面逐一解释: 现在这个新闻单例就是线程安全的了。下面我们看一下完整的代码: import Foundation
class NewsFeed {
static let sharedInstance = NewsFeed()
private let concurrentQueue = dispatch_queue_create("newsfeed.queue.concurrent",DISPATCH_QUEUE_CONCURRENT)
private init() {}
private var _news: [String] = []
var news: [String] {
var newsCopy: [String]!
dispatch_sync(concurrentQueue){
newsCopy = self._news
}
return newsCopy
}
func addNews(n: String) {
dispatch_barrier_async(concurrentQueue){
self._news.append(n)
dispatch_async(dispatch_get_main_queue()){
self.newsAddedNotification()
}
}
}
func newsAddedNotification() {
// post notification
}
}
欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 330987132 | nodejs:329118122 | Go-Scala:217696290 | Python:336880185 | 做人要厚道,转载请注明出处! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |