Java并发编程---并发类容器(ConcurrentMap容器)

我不是女神ヾ 2022-06-02 02:57 827阅读 0赞

一.背景前奏

jdk5.0以后提供了多种并发类容器来替代同步类容器从而改善性能.同步类容器的状态都是串行化的.他们虽然实现了线程安全.但是严重降低了并发性,在多线程环境时,严重降低了应用程序的吞吐量.

并发类容器是专门针对并发设计的使用ConcurrentHashMap来代替给予散列的传统的HashTable,而且在ConcurrentHashMap中,添加了一些常见复合操作的支持.以及使用了CopyOnWriteArrayList代替Vector,并发的CopyOnWriteArraySet,以及并发地Queue,ConcurrentLinkedQueue和LinkedBlockingQueue,前者是高性能的队列,后者是以阻塞形式的队列,具体实现Queue还有很多,例如ArrayBlockingQueue,PriorityBlockingQueue,synchronousQueue等.

二.ConcurrentMap概念

ConcurrentMap接口下有两个重要的实现:

ConcurrentHashMap

ConcurrentSkipListMap(支持并发排序功能,补充ConcurrentHashMap)

ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每一段其实就是一个小的HashTable,它们有自己的锁.只要多个修改操作发生在不同的段上,它们就可以并发进行.把一个整体分成16个段(Segment).也就是最高支持16个线程的并发修改操作.这也是多线程场景时减少锁的粒度从而降低锁竞争的一种方案,并且代码中大多共享变量使用Volatile关键字声明,目的是第一时间获取修改的内容,性能非常好.

三.代码示例

private ConcurrentHashMap> map = new ConcurrentHashMap>();

  1. package com.thread.message;
  2. import java.util.LinkedList;
  3. import java.util.concurrent.ConcurrentHashMap;
  4. import java.util.concurrent.TimeUnit;
  5. import java.util.concurrent.atomic.AtomicInteger;
  6. public class MyQueue {
  7. //1.需要一个承载元素的集合
  8. LinkedList<Object> list = new LinkedList<Object>();
  9. //2.需要一个计数器(统计linkedList的个数)
  10. private AtomicInteger count = new AtomicInteger(0);
  11. //应该设置ConcurrentHashMap容器的上限,如10个(根据该数据结构,适当修改业务逻辑)
  12. private ConcurrentHashMap<String,ConcurrentHashMap<String, Integer>> map = new ConcurrentHashMap<String,ConcurrentHashMap<String, Integer>>();
  13. //3.需要制约上限和下限
  14. private final int minSize = 0;
  15. private int maxSize;
  16. //4.构造方法
  17. public MyQueue(int size) {
  18. this.maxSize = maxSize;
  19. }
  20. //5.初始化一个对象,用于加锁
  21. private final Object lock = new Object();
  22. //put(anObject):把anObject加到BlockingQueue里,如果BlockingQueue没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继续
  23. public void put(Object obj){
  24. synchronized (lock) {
  25. while(count.get() == this.maxSize){
  26. try {
  27. lock.wait();
  28. } catch (InterruptedException e) {
  29. // TODO Auto-generated catch block
  30. e.printStackTrace();
  31. }
  32. }
  33. //1.加入元素
  34. list.add(obj);
  35. //2.计数器累加
  36. count.incrementAndGet(); //加1后notify
  37. //通知另外一个线程(唤醒)
  38. lock.notify();
  39. System.out.println("新加入的元素为: " + obj);
  40. }
  41. }
  42. //take: 取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态,直到BlockingQueue有新的数据被加入
  43. public Object take(){
  44. Object ret = null;
  45. synchronized (lock) {
  46. while(count.get() == this.maxSize){
  47. try {
  48. lock.wait();
  49. } catch (InterruptedException e) {
  50. // TODO Auto-generated catch block
  51. e.printStackTrace();
  52. }
  53. }
  54. //1.做移除元素操作
  55. ret = list.removeFirst();
  56. //2.计数器递减
  57. count.decrementAndGet();
  58. //3.唤醒另外一个线程
  59. lock.notify();
  60. }
  61. return ret;
  62. }
  63. public int getSize(){
  64. return this.count.get();
  65. }
  66. public static void main(String[] args) {
  67. // TODO Auto-generated method stub
  68. final MyQueue mq = new MyQueue(5);
  69. mq.put("a");
  70. mq.put("b");
  71. mq.put("c");
  72. mq.put("d");
  73. mq.put("e");
  74. System.out.println("当前容器的长度: " + mq.getSize());
  75. Thread t1 = new Thread(new Runnable() {
  76. @Override
  77. public void run() {
  78. // TODO Auto-generated method stub
  79. mq.put("f");
  80. mq.put("g");
  81. }
  82. },"t1");
  83. t1.start();
  84. Thread t2 = new Thread(new Runnable() {
  85. @Override
  86. public void run() {
  87. // TODO Auto-generated method stub
  88. Object o1 = mq.take();
  89. System.out.println("移除的元素为: " + o1);
  90. Object o2 = mq.take();
  91. System.out.println("移除的元素为: " + o2);
  92. }
  93. },"t2");
  94. try {
  95. TimeUnit.SECONDS.sleep(2);
  96. } catch (InterruptedException e) {
  97. // TODO Auto-generated catch block
  98. e.printStackTrace();
  99. }
  100. t2.start();
  101. }
  102. }

发表评论

表情:
评论列表 (有 0 条评论,827人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java并发编程---同步容器

    一.概念 同步类容器都是线程安全的,但在某些场景下可能需要加锁来保护复合操作.复合类操作如:迭代(反复访问元素,遍历完容器中所有的元素),跳转(根据指定的顺序找到当前元素的下