实现一个线程安全的栈

这里使用数组来存储栈的数据。不足之处在于本例中的Stack可以无限扩容,更好的是初始化时候指定一个最大容量,防止不断扩容申请内存导致内存不够的问题。这里的线程安全使用一个串行队列来保证,实际上也可以通过加锁或者信号量甚至自旋锁来解决。

  1. struct Stack<Element> {
  2. private var items: [Element]
  3. private var queue = DispatchQueue(label: "StackOperationQueue")
  4. public init(capacity: Int = 10) {
  5. items = [Element]()
  6. items.reserveCapacity(capacity)
  7. }
  8. mutating public func push(item: Element) {
  9. queue.sync {
  10. items.append(item)
  11. }
  12. }
  13. mutating public func pop() -> Element? {
  14. var item: Element?
  15. queue.sync {
  16. item = items.removeLast()
  17. }
  18. return item
  19. }
  20. }

实现一个线程安全的队列

  1. // 存储数据的双向链表节点
  2. class DoubleLinkNode<Element> {
  3. var previous: DoubleLinkNode?
  4. var next: DoubleLinkNode?
  5. let val: Element?
  6. init(val: Element?) {
  7. self.val = val
  8. }
  9. //声明==运算符,便于判断两个节点是否相等
  10. static func ==(left: DoubleLinkNode<Element>, right: DoubleLinkNode<Element>) -> Bool {
  11. //最准确的做法是判断内存地址是否相同
  12. let leftPointValue = Unmanaged<AnyObject>.passUnretained(left).toOpaque()
  13. let rightPointValue = Unmanaged<AnyObject>.passUnretained(right).toOpaque()
  14. return leftPointValue == rightPointValue
  15. }
  16. }
  17. /*
  18. 1.使用双向链表实现队列结构,声明空的head/last哨兵节点简化双向链表操作;
  19. 2.使用串行队列保证线程安全,实际上也可以通过加锁的方式实现线程安全;
  20. 3.对于生产者-消费者模型,这里可以使用semaphore来实现,当队列为空的时候,让线程休眠,当有元素入队的时候唤醒一个线程继续执行任务。
  21. */
  22. struct Queue<Element> {
  23. //声明串行队列,将操作放在串行队列中,保证线程安全
  24. private var queue = DispatchQueue(label: "QueueOperationQueue")
  25. let firstNode: DoubleLinkNode<Element>
  26. let lastNode: DoubleLinkNode<Element>
  27. public init(capacity: Int = 20) {
  28. firstNode = DoubleLinkNode(val: nil)
  29. lastNode = DoubleLinkNode(val: nil)
  30. firstNode.next = lastNode
  31. lastNode.previous = firstNode
  32. }
  33. /// 入队操作
  34. mutating public func enqueue(item: Element) {
  35. queue.sync {
  36. let node = DoubleLinkNode<Element>(val: item)
  37. let tmp = firstNode.next
  38. firstNode.next = node
  39. node.previous = firstNode
  40. node.next = tmp
  41. tmp?.previous = node
  42. }
  43. }
  44. /// 出队操作
  45. mutating public func dequeue() -> Element? {
  46. guard let previous = lastNode.previous, !(firstNode == previous) else { return nil }
  47. var node: DoubleLinkNode<Element>? = nil
  48. queue.sync {
  49. node = lastNode.previous
  50. node?.next = nil
  51. node?.previous = nil
  52. let tmp = node?.previous
  53. lastNode.previous = tmp
  54. tmp?.next = lastNode
  55. }
  56. return node?.val
  57. }
  58. }

swift实现线程安全的栈和队列的更多相关文章

  1. Swift 算法实战之路:栈和队列

    这期的内容有点剑走偏锋,我们来讨论一下栈和队列.Swift语言中没有内设的栈和队列,很多扩展库中使用Generic Type来实现栈或是队列.笔者觉得最实用的实现方法是使用数组,本期主要内容有: 栈和 ...

  2. 算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)

    数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用.因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队列.本篇博客其实就是<数据结构之线 ...

  3. [Swift]LeetCode232. 用栈实现队列 | Implement Queue using Stacks

    Implement the following operations of a queue using stacks. push(x) -- Push element x to the back of ...

  4. swift语言之多线程操作和操作队列(下)———坚持51天吃掉大象(写技术文章)

    欢迎有兴趣的朋友,参与我的美女同事发起的活动<51天吃掉大象>,该美女真的很疯狂,希望和大家一起坚持51天做一件事情,我加入这个队伍,希望坚持51天每天写一篇技术文章.关注她的微信公众号: ...

  5. java集合详解(附栈,队列)

    1 集合 1.1 为什么会出现集合框架 [1] 之前的数组作为容器时,不能自动拓容 [2] 数值在进行添加和删除操作时,需要开发者自己实现添加和删除. 1.2 Collection接口 1.2.1 C ...

  6. 什么是“堆”,"栈","堆栈","队列",它们的区别?

    堆:什么是堆?又该怎么理解呢? ①堆通常是一个可以被看做一棵树的数组对象.堆总是满足下列性质: ·堆中某个节点的值总是不大于或不小于其父节点的值: ·堆总是一棵完全二叉树. 将根节点最大的堆叫做最大堆 ...

  7. 纯数据结构Java实现(2/11)(栈与队列)

    栈和队列的应用非常多,但是起实现嘛,其实很少人关心. 但问题是,虽然苹果一直宣传什么最小年龄的编程者,它试图把编程大众化,弱智化,但真正的复杂问题,需要抽丝剥茧的时候,还是要 PRO 人士出场,所以知 ...

  8. 堆”,"栈","堆栈","队列"以及它们的区别

    如果你学过数据结构,就一定会遇到“堆”,"栈","堆栈","队列",而最关键的是这些到底是什么意思?最关键的是即使你去面试,这些都还会问到, ...

  9. 【PHP数据结构】栈和队列的应用

    通过栈和队列的学习,我们似乎会感觉到其实数据结构还是非常简单的嘛.当然,这只是一个开始,我们从顺序表.链表开始,到现在的栈和队列,其实都是为了将来在铺路.在树和图的遍历算法中,都可以见到栈和队列的身影 ...

随机推荐

  1. 有了二叉查找树、平衡树(AVL)为啥还需要红黑树?

    序言 二叉查找树的缺点 平衡二叉树 虽然平衡树解决了二叉查找树退化为近似链表的缺点,能够把查找时间控制在 O(logn),不过却不是最佳的,因为平衡树要求每个节点的左子树和右子树的高度差至多等于1,这 ...

  2. 【bzoj3195】【 [Jxoi2012]奇怪的道路】另类压缩的状压dp好题

    (上不了p站我要死了) 啊啊,其实想清楚了还是挺简单的. Description 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外.考古学家已经知道,这个文明在全盛时期 ...

  3. 【bzoj3676】[Apio2014]回文串

    *题目描述: 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最大出现值. *输入: 输入只有一行,为一个只包含小 ...

  4. 特征提取算法(4)——Harris角点提取

    1.角点 1.1 特征点与角点 特征点是计算机视觉算法的基础,使用特征点来代表图像的内容. 角点是一类重要的点特征,图像分析的角度来定义: 角点可以是两个边缘的角点: 角点是邻域内具有两个主方向的特征 ...

  5. KNN算法之KD树

    KD树算法是先对数据集进行建模,然后搜索最近邻,最后一步是预测. KD树中的K指的是样本特征的维数. 一.KD树的建立 m个样本n维特征,计算n个特征的方差,取方差最大的第k维特征作为根节点.选择第k ...

  6. RedisTemplate访问Redis数据结构(前言)

    Redis五种基本数据结构 redis提供键值对的形式对数据进行存储.支持五种数据类型:String(字符串),List(链表),Hash(散列),Set(无序集合),ZSet(有序集合).下面是网上 ...

  7. 小程序cover-view

    cover-view包裹的元素设置定位,元素内容长短会影响cover-view的位置,即使设置的left,top一致 最佳解决方法,就是给cover-view设置宽度

  8. elasticsearch堆内存的配置建议

    1.将最小堆大小(Xms)和最大堆大小(Xmx)设置为彼此相等 防止内存抖动 2:给多大的堆内存? 给ES的内存配置不是越大越好,建议不能超过32GB,不同jdk版本最大边界值是不同的,对于32位小于 ...

  9. 高清摄像头MIPI接口与ARM连接【转】

    本文转载自:http://www.cnblogs.com/whw19818/p/5811299.html MIPI摄像头常见于手机.平板中,支持500万像素以上高清分辨率.它的全称为“Mobile I ...

  10. Uncaught TypeError: Cannot read property 'length' of null错误怎么处理?

    Uncaught TypeError: Cannot read property 'length' of null 错误怎么处理? 1.可能是返回的datagrid数据格式有问题,比如{"t ...