并发容器简介
来源:互联网 发布:淘宝极有家有假货么 编辑:程序博客网 时间:2024/06/05 11:30
CurrentHashMap: 线程安全的HashMap
另一种线程安全的HashMap
public static Map m = Collections.synchronizedMap(new HashMap());//实现方式//但并发性不高public V get(Object key) { synchronized (mutex) {return m.get(key);}}
CopyOnWriteArrayList: 适用于读多写少的场合,性能好于Vector
只有写写之间是会阻塞的。在写入的时候会进行一次自我复制,将修改的内容写入副本中,写完之后,再将修改完的副本替换原来的数据。
//读取private volatile transient Object[] array;public E get(int index){ return get(getArray(), index);}final Object[] getArray(){ return array;}private E get(Object[] a, int index){ return (E) a[index]}//写入public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); }}
ConcurrentLinkedQueue: 线程安全的链表队列
这是在高并发环境下性能最好的队列了,前提是高并发(至少1000个线程)
(据测试,性能和Vector差不了多少)
//链表节点private static class Node<E>{ volatile E item; volatile Node<E> next;}//tail代表的节点,可能会有延时现象,即tail并不是指向最后一个节点。//每次更新会跳跃两个元素来更新tail指针// head == tail// head(== tail) -> Node// head -> Node -> Node(tail)// head -> Node -> Node(tail) -> Node// head -> Node -> Node -> Node -> Node(tail) public boolean offer(E e) { checkNotNull(e); final Node<E> newNode = new Node<E>(e); for (Node<E> t = tail, p = t;;) { Node<E> q = p.next; if (q == null) { // p是最后一个节点 if (p.casNext(null, newNode)) { //每两次更新一下tail if (p != t) // hop two nodes at a time casTail(t, newNode); // Failure is OK. return true; } //如果CAS失败了,会在循环中再次尝试 } else if (p == q) //遇到哨兵节点,从head开始便历 //但如果tail被修改了,则使用tail(因为可能被修改正确了) p = (t != (t = tail)) ? t : head; else //取下一个节点或者最后一个节点 p = (p != t && t != (t = tail)) ? t : q; } } public E poll() { restartFromHead: for (;;) { for (Node<E> h = head, p = h, q;;) { E item = p.item; if (item != null && p.casItem(item, null)) { // Successful CAS is the linearization point // for item to be removed from this queue. if (p != h) // hop two nodes at a time updateHead(h, ((q = p.next) != null) ? q : p); return item; } else if ((q = p.next) == null) { updateHead(h, p); return null; } else if (p == q) continue restartFromHead; else p = q; } } } //设置当前的Node的item值,当cmp==当前值,设置为val boolean casItem(E cmp,E val){ return UNSAFE.compareAndSwapObject(this,itemOffset,cmp,val); } // void lazySetNext(Node<E> val){ UNSAFE.putOrderedObject(this, nextOffset,val); } boolean casNext(Node<E> cmp, Node<E> val){ return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } final void updateHead(Node<E> h,Node<E> p){ if(h != p && casHead(h,p) h.lazySetNext(h);w }
BlockingQueue: 一个接口,堵塞队列,作为数据共享的通道。就想物业的人设立一个邮箱,业主可以往这个邮箱里面投递投诉意见。业主会变,物业的工作人员也会变,但是信箱的作用不变。
实现接口的类有ArrayBlockingQueue和LinkedBlockingQueue。ArrayBlockingQueue适合实现有界队列,而LinkedBlockingQueue适合实现无界队列。
offer():将元素放入队列尾,满了会返回false || poll(): 头部取出一个元素,队列空返回null
put():将元素放入队列尾,满了会一直等待,直到有空闲 || take(): 头部取出,队列空则堵塞等待
public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); enqueue(e); } finally { lock.unlock(); } }public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) notEmpty.await(); return dequeue(); } finally { lock.unlock(); } }public boolean offer(E e) { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lock(); try { if (count == items.length) return false; else { enqueue(e); return true; } } finally { lock.unlock(); } }public E poll() { final ReentrantLock lock = this.lock; lock.lock(); try { return (count == 0) ? null : dequeue(); } finally { lock.unlock(); } }
ConcurrentSkipListMap: 跳表的实现
最低层的链表维护了跳表的所有元素,上一层链表为下一层链表的子集。跳表的元素都是有序的,查找时从顶层链表开始查找,发现被查找的元素大于当前链表的中的取值,则会进入下一层链表进行查找。
跳表是一种空间换时间的实现,但比HashMap好的是,跳表是有序的。
阅读全文
0 0
- 并发容器简介
- Java多线程——并发容器简介
- Java并发容器之阻塞队列简介
- Java并发包中CopyOnWrite容器相关类简介
- Java并发包中CopyOnWrite容器相关类简介
- 并发容器
- 并发容器
- 并发容器
- 并发容器
- 并发容器
- 并发容器
- 并发容器
- 并发容器
- 并发容器
- 并发容器
- 同步容器&并发容器
- 深入浅出 Java Concurrency (19): 并发容器 part 4 并发队列与Queue简介
- 容器简介
- 二层交换机的工作原理
- putty上SSH的端口转发设置
- SPOJ
- android 截图功能源码解析
- Linux配置yum源
- 并发容器简介
- 图像有用区域(广搜)
- 通过RTL电路深入理解阻塞赋值和非阻塞赋值的区别
- Meta标签中的format-detection属性及含义
- [ubuntu]相关库安装出错--解决方法
- nrf中断处理的优先级
- Java 编程思想(三)集合容器
- Intellij 小技巧 演示模式
- 回调函数,一个神奇的东西