swift实现线程安全的栈和队列
实现一个线程安全的栈
这里使用数组来存储栈的数据。不足之处在于本例中的Stack可以无限扩容,更好的是初始化时候指定一个最大容量,防止不断扩容申请内存导致内存不够的问题。这里的线程安全使用一个串行队列来保证,实际上也可以通过加锁或者信号量甚至自旋锁来解决。
struct Stack<Element> {
private var items: [Element]
private var queue = DispatchQueue(label: "StackOperationQueue")
public init(capacity: Int = 10) {
items = [Element]()
items.reserveCapacity(capacity)
}
mutating public func push(item: Element) {
queue.sync {
items.append(item)
}
}
mutating public func pop() -> Element? {
var item: Element?
queue.sync {
item = items.removeLast()
}
return item
}
}
实现一个线程安全的队列
// 存储数据的双向链表节点
class DoubleLinkNode<Element> {
var previous: DoubleLinkNode?
var next: DoubleLinkNode?
let val: Element?
init(val: Element?) {
self.val = val
}
//声明==运算符,便于判断两个节点是否相等
static func ==(left: DoubleLinkNode<Element>, right: DoubleLinkNode<Element>) -> Bool {
//最准确的做法是判断内存地址是否相同
let leftPointValue = Unmanaged<AnyObject>.passUnretained(left).toOpaque()
let rightPointValue = Unmanaged<AnyObject>.passUnretained(right).toOpaque()
return leftPointValue == rightPointValue
}
}
/*
1.使用双向链表实现队列结构,声明空的head/last哨兵节点简化双向链表操作;
2.使用串行队列保证线程安全,实际上也可以通过加锁的方式实现线程安全;
3.对于生产者-消费者模型,这里可以使用semaphore来实现,当队列为空的时候,让线程休眠,当有元素入队的时候唤醒一个线程继续执行任务。
*/
struct Queue<Element> {
//声明串行队列,将操作放在串行队列中,保证线程安全
private var queue = DispatchQueue(label: "QueueOperationQueue")
let firstNode: DoubleLinkNode<Element>
let lastNode: DoubleLinkNode<Element>
public init(capacity: Int = 20) {
firstNode = DoubleLinkNode(val: nil)
lastNode = DoubleLinkNode(val: nil)
firstNode.next = lastNode
lastNode.previous = firstNode
}
/// 入队操作
mutating public func enqueue(item: Element) {
queue.sync {
let node = DoubleLinkNode<Element>(val: item)
let tmp = firstNode.next
firstNode.next = node
node.previous = firstNode
node.next = tmp
tmp?.previous = node
}
}
/// 出队操作
mutating public func dequeue() -> Element? {
guard let previous = lastNode.previous, !(firstNode == previous) else { return nil }
var node: DoubleLinkNode<Element>? = nil
queue.sync {
node = lastNode.previous
node?.next = nil
node?.previous = nil
let tmp = node?.previous
lastNode.previous = tmp
tmp?.next = lastNode
}
return node?.val
}
}
swift实现线程安全的栈和队列的更多相关文章
- Swift 算法实战之路:栈和队列
这期的内容有点剑走偏锋,我们来讨论一下栈和队列.Swift语言中没有内设的栈和队列,很多扩展库中使用Generic Type来实现栈或是队列.笔者觉得最实用的实现方法是使用数组,本期主要内容有: 栈和 ...
- 算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)
数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用.因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队列.本篇博客其实就是<数据结构之线 ...
- [Swift]LeetCode232. 用栈实现队列 | Implement Queue using Stacks
Implement the following operations of a queue using stacks. push(x) -- Push element x to the back of ...
- swift语言之多线程操作和操作队列(下)———坚持51天吃掉大象(写技术文章)
欢迎有兴趣的朋友,参与我的美女同事发起的活动<51天吃掉大象>,该美女真的很疯狂,希望和大家一起坚持51天做一件事情,我加入这个队伍,希望坚持51天每天写一篇技术文章.关注她的微信公众号: ...
- java集合详解(附栈,队列)
1 集合 1.1 为什么会出现集合框架 [1] 之前的数组作为容器时,不能自动拓容 [2] 数值在进行添加和删除操作时,需要开发者自己实现添加和删除. 1.2 Collection接口 1.2.1 C ...
- 什么是“堆”,"栈","堆栈","队列",它们的区别?
堆:什么是堆?又该怎么理解呢? ①堆通常是一个可以被看做一棵树的数组对象.堆总是满足下列性质: ·堆中某个节点的值总是不大于或不小于其父节点的值: ·堆总是一棵完全二叉树. 将根节点最大的堆叫做最大堆 ...
- 纯数据结构Java实现(2/11)(栈与队列)
栈和队列的应用非常多,但是起实现嘛,其实很少人关心. 但问题是,虽然苹果一直宣传什么最小年龄的编程者,它试图把编程大众化,弱智化,但真正的复杂问题,需要抽丝剥茧的时候,还是要 PRO 人士出场,所以知 ...
- 堆”,"栈","堆栈","队列"以及它们的区别
如果你学过数据结构,就一定会遇到“堆”,"栈","堆栈","队列",而最关键的是这些到底是什么意思?最关键的是即使你去面试,这些都还会问到, ...
- 【PHP数据结构】栈和队列的应用
通过栈和队列的学习,我们似乎会感觉到其实数据结构还是非常简单的嘛.当然,这只是一个开始,我们从顺序表.链表开始,到现在的栈和队列,其实都是为了将来在铺路.在树和图的遍历算法中,都可以见到栈和队列的身影 ...
随机推荐
- 10分钟学会React Context API
Create-react-app来学习这个功能: 注意下面代码红色的即可,非常简单. 在小项目里Context API完全可以替换掉react-redux. 修改app.js import React ...
- 如何理解重载与重写——Overload vs Override/Overwrite
重载: 在同一个类中,拥有类似功能的同名方法之间的关系叫做重载. 重载的条件:1.具有相同方法名和类似功能: 2.参数的类型或者个数不同: 3.与返回值无关: 重写: 在子父类的继承关系中,子类继承父 ...
- JS-Proxy
Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等). 参考:Proxy - JavaScript | MDN 语法: let p = new Proxy(target, ...
- 关于崩溃报告的日志以及dump文件
在用户使用软件的过程当中突然产生软件崩溃的问题,必须采取相关的措施去拦截崩溃产生的原因,这有助于程序员解决此类崩溃的再次发生.特别是有些难以复现的崩溃,不稳定的崩溃,更有必要去调查崩溃产生的原因.一般 ...
- UI自动化之三种等待
UI自动化中常用三种等待 目录 1.强制等待 2.隐式等待 3.显示等待 1.强制等待 执行到某一条语句后,然后sleep(3),等待3秒后,才会继续执行后面的语句 2.隐式等待 隐式等待只需要声明一 ...
- adbl连接不上 daemon not running. starting it now on port 5037 ADB server didn't ACK
http://blog.csdn.net/prettyice2005/article/details/38682443 adbl连接不上 daemon not running. starting i ...
- android window(三)lWindow添加流程
http://androidxref.com/6.0.1_r10/xref/frameworks/base/services/core/java/com/android/server/wm/Windo ...
- 观察者模式(jdk实现)
1.定义 在对象中定义一对多的依赖,当一个对象改变状态,依赖它的对象会收到通知并更新. 2.实现 (主要通过jdk自己定义的观察者实现) 以气象站通知展示板为例子,当气象站收到的各种参数改变的时候 ...
- Reinforcement Learning Index Page
Reinforcement Learning Posts Step-by-step from Markov Property to Markov Decision Process Markov Dec ...
- 腾讯视频的手机端的地址和PC端的地址是不一样的
腾讯视频的手机端的地址和PC端的地址是不一样的,所以使用iframe的时候记得要使用手机端的地址