实现一个线程安全的栈

这里使用数组来存储栈的数据。不足之处在于本例中的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
}
}

最新文章

  1. jsp中头的导入两种方式区别
  2. Emacs学习心得之 LaTeX编辑
  3. 初识android中的动画
  4. wex5 实战 框架拓展之1 公共data组件(Data)
  5. Rxjava的基本使用
  6. [转]全面理解Unity加载和内存管理
  7. 【转】 制作Android Demo GIF:程序演示效果GIF图录制
  8. 期望DP
  9. Android--使用VideoView播放视频
  10. Hadoop概括——学习笔记&lt;一&gt;转
  11. C# 实现Oracle中的数据与Excel之间的转换
  12. Ubuntu11.10 E: Unable to locate package ubuntu-restricted-extras
  13. Java并发,看到了,就记录下呗
  14. 【网站公告】请大家不要发表任何涉及“得到App”的内容
  15. I/O模型系列之三:IO通信模型BIO NIO AIO
  16. 【原创】使用golang访问windows telnet服务器
  17. Debian ifconfig 命令找不到
  18. JSON字符串互相转换的三种方式和性能比较
  19. Codeforces Round #524 (Div. 2) F. Katya and Segments Sets(主席树)
  20. 配置postgres9.3间的fdw——实现不同postgres数据库间的互访问

热门文章

  1. 报错信息:ORA-00979:不是GROUP BY表达式
  2. [design pattern](1) Strategy
  3. 官方文档翻译-Today
  4. shell 中使用正则表达式
  5. 关于openGL、GPUImage、ios直播相关不错的博客
  6. Jenkins获取运行job的用户名(在构建历史中展示构建人)
  7. Linux_SquidProxyServer代理服务器
  8. Linux_LAMP 最强大的动态网站解决方案
  9. 【ABAP系列】SAP WEB GUI的实现,SAP在网页中使用
  10. 【ABAP系列】SAP ABAP实现发送外部邮件(添加附件)功能