目录

同步类容器

并发类容器

ConcurrentMap:支持高并发下线程安全。

Copy-On-Write容器:最好在读多写少的情况下使用。

并发Queue


同步类容器

同步类容器是线程安全的。

//HashMap不是线程安全的,但是这样做之后就是线程安全的。
Map<String, String> map = Collections.synchronizedMap(new  HashMap<String, String>());Vector类 是在 java 中可以实现自动增长的对象数组,线程安全的。
Vector<String> tickets = new Vector<String>();
HashTable、Vector,其底层的机制就是用传统的synchronized关键字对每个公共方法进行同步,所以性能较差。

并发类容器

ConcurrentHashMap代替了HashTable。

CopyOnWriteArrayList代替了Voctor。

以及并发的CopyonWriteArraySet。

以及并发的Queue,ConcurrentLinkedQueue(高性能队列)和LinkedBlockingQueue(阻塞形式的队列);具体的Queue还有很多,例如ArrayBlockingQueue、PriorityBlockingQueue、SynchronousQueue。

ConcurrentMap:支持高并发下线程安全。

ConcurrentHashMap代替HashTable:

HashTable底层机制是用传统的synchronized关键字对每个公共方法进行同步,性能较差。

ConcurrentHashMap底层有一个segment(段)的概念最多分16个段,把一个HashTable分成许多段,相当于形成许多小的HashTable,通过减小锁的粒度,减小锁竞争的问题,底层大量使用volatile关键字声明,目的是第一时间获取修改的内容,性能非常好。

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

ConcurrentHashMap<String, Object> chm = new  ConcurrentHashMap<String, Object>();
chm.put("k1", "v1");
chm.put("k2", "v2");
chm.put("k3", "v3");
chm.putIfAbsent("k4", "vvvv");//重复不加,不重复就加。
//System.out.println(chm.get("k2"));
//System.out.println(chm.size());
for(Map.Entry<String, Object> me : chm.entrySet()){System.out.println("key:" + me.getKey() + ",value:" +  me.getValue());
}

Copy-On-Write容器:最好在读多写少的情况下使用。

对一个容器进行写操作的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器进行写操作;操作完成之后,再将原容器的引用指向新的容器。这样做的好处是可以对CopyOnWrite容器进行并发的读,而不需要加锁。所以CopyOnWrite容器是一种读写分离的思想,读和写不同的容器。

CopyOnWriteArrayList<String> cwal = new  CopyOnWriteArrayList<String>();
CopyOnWriteArraySet<String> cwas = new  CopyOnWriteArraySet<String>();
在add、remove等方法加了锁,重入锁。java.util.concurrent.locks.ReentrantLock

并发Queue

ConcurrentLinkedQueue为代表的高性能队列;BlockingQueue接口为代表的阻塞队列。

ConcurrentLinkedQueue:适用于高并发,无锁、先进先出、不允许null元素。
ConcurrentLinkedQueue重要方法:
add()和offer()都是加入元素(在ConcurrentLinkedQueue中这俩方法没有任何区别);
poll()和peek()都是取头元素节点,前者会删除元素,后者不会。//高性能无阻塞无界队列:ConcurrentLinkedQueue
ConcurrentLinkedQueue<String> q = new  ConcurrentLinkedQueue<String>();
q.offer("a");
q.offer("b");
q.offer("c");
q.offer("d");
q.add("e");
System.out.println(q.poll());   //a 从头部取出元素,并从队列里删除
System.out.println(q.size());   //4
System.out.println(q.peek());   //b
System.out.println(q.size());   //4
ArrayBlockingQueue:基于数组实现的阻塞队列。内部维护了一个定长数组,以便缓存队列中的数据对象,其内部没实现读写分离,也就意味着生产和消费不能完全并行,长度是需要定义的,可以指定先进先出或者先进后出,也叫有界队列。
LinkedBlockingQueue:基于链表的阻塞队列,同ArrayBlockingQueue类似,其内部维持着一个数据缓冲队列(该队列由一个链表构成),LinkedBlockingQueue之所以能够高效的处理并发数据,是因为其内部实现采用分离锁(读写分离两个锁),从而实现生产者和消费者操作的完全并行运行。它是一个无界队列。
SynchronousQueue:一种没有缓冲的队列,生产者产生的数据直接会被消费者获取并消费。ArrayBlockingQueue<String> array = new  ArrayBlockingQueue<String>(5);
array.put("a");
array.put("b");
array.add("c");
array.add("d");
array.add("e");
array.add("f");//最多5个,超长报错
//System.out.println(array.offer("a", 3, TimeUnit.SECONDS));//返回true或false//阻塞队列
LinkedBlockingQueue<String> q = new  LinkedBlockingQueue<String>(5);//不声明长度的话,就是无界队列
q.offer("a");
q.offer("b");
q.offer("c");
q.offer("d");
q.offer("e");
q.add("f");//声明了5,但是用offer还添加的话添加不上,用add添加会报错。
//System.out.println(q.size());
for (Iterator iterator = q.iterator(); iterator.hasNext();) {String string = (String) iterator.next();System.out.println(string);
}
List<String> list = new ArrayList<String>();
System.out.println(q.drainTo(list, 3));//从队列中取3个元素放到集合里。3
System.out.println(list.size());//3
for (String string : list) {System.out.println(string);
}final SynchronousQueue<String> q = new  SynchronousQueue<String>();
//q.add("asdasd");//直接这样加会报错
Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {try {System.out.println(q.take());//会阻塞} catch (InterruptedException e) {e.printStackTrace();}}
});
t1.start();
Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {q.add("asdasd");}
});
t2.start();     
PriorityBlockingQueue:基于优先级的阻塞队列(优先级的判断通过构造函数传入的Compator对象来决定,也就是说传入队列的对象必须实现Comparable接口),在实现PriorityBlockingQueue时,内部控制线程同步的锁采用的是公平锁,他也是一个无界的队列。public class Task implements Comparable<Task>{private int id ;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic int compareTo(Task task) {return this.id > task.id ? 1 : (this.id < task.id ?  -1 : 0);  }public String toString(){return this.id + "," + this.name;}
}PriorityBlockingQueue<Task> q = new  PriorityBlockingQueue<Task>();
Task t1 = new Task();
t1.setId(3);
t1.setName("id为3");
Task t2 = new Task();
t2.setId(4);
t2.setName("id为4");
Task t3 = new Task();
t3.setId(1);
t3.setName("id为1");
//return this.id > task.id ? 1 : 0;
q.add(t1); //3
q.add(t2); //4
q.add(t3);  //1//并不是添加元素之后就排序
System.out.println("容器:" + q);//容器:[1,id为1, 4,id为4, 3,id为3]
System.out.println(q.take().getId());//调用take方法之后把优先级最高的元素拿出来
System.out.println("容器:" + q);
DelayQueue:带有延迟时间的Queue,其中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue中的元素必须实现Delayed接口,DelayQueue是一个没有大小限制的队列,应用场景很多,比如对缓存超时的数据进行移除、任务超时处理、空闲连接的关闭等等。
public class WangBa implements Runnable {  private DelayQueue<Wangmin> queue = new  DelayQueue<Wangmin>();  public boolean yinye =true;  public void shangji(String name,String id,int money){  Wangmin man = new Wangmin(name, id, 1000 * money +  System.currentTimeMillis());  System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"交钱"+money+"块,开始上机...");  this.queue.add(man);  }  public void xiaji(Wangmin man){  System.out.println("网名"+man.getName()+" 身份证"+man.getId()+"时间到下机...");  }  @Override  public void run() {  while(yinye){  try {  Wangmin man = queue.take();  xiaji(man);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }  public static void main(String args[]){  try{  System.out.println("网吧开始营业");  WangBa siyu = new WangBa();  Thread shangwang = new Thread(siyu);  shangwang.start();  siyu.shangji("路人甲", "123", 1);  siyu.shangji("路人乙", "234", 10);  siyu.shangji("路人丙", "345", 5);  }  catch(Exception e){  e.printStackTrace();}  }
}  public class Wangmin implements Delayed {  private String name;  //身份证  private String id;  //截止时间  private long endTime;  //定义时间工具类private TimeUnit timeUnit = TimeUnit.SECONDS;public Wangmin(String name,String id,long endTime){  this.name=name;  this.id=id;  this.endTime = endTime;  }  public String getName(){  return this.name;  }  public String getId(){  return this.id;  }  /*** 用来判断是否到了截止时间*/  @Override  public long getDelay(TimeUnit unit) {//return unit.convert(endTime, TimeUnit.MILLISECONDS) -  unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);return endTime - System.currentTimeMillis();}  /*** 相互批较排序用*/  @Override  public int compareTo(Delayed delayed) {  Wangmin w = (Wangmin)delayed;  return this.getDelay(this.timeUnit) -  w.getDelay(this.timeUnit) > 0 ? 1:0;  }
}  

谈谈java的并发容器、Queue相关推荐

  1. java常见并发容器

    并发容器 引言 为了应对高并发过程中,数据一致性的问题,java中设计了一些并发容器.本篇将从容器的类别出发,介绍各个容器的特点及原理,为接下来的线程池做准备. List相关 Vector Vecto ...

  2. Java集合之并发容器

    一:java中的并发容器总结 JDK提供的这些容器大部分在 java.util.concurrent 包中. ConcurrentHashMap: 线程安全的HashMap CopyOnWriteAr ...

  3. java 并发queue_深入浅出 Java Concurrency (19): 并发容器 part 4 并发队列与Queue简介

    Queue是JDK 5以后引入的新的集合类,它属于Java Collections Framework的成员,在Collection集合中和List/Set是同一级别的接口.通常来讲Queue描述的是 ...

  4. 探索JAVA并发 - 并发容器全家福!

    作者:acupt,专注Java,架构师社区合伙人! 14个并发容器,你用过几个? 不考虑多线程并发的情况下,容器类一般使用ArrayList.HashMap等线程不安全的类,效率更高.在并发场景下,常 ...

  5. java 头尾 队列_探索JAVA并发 - 并发容器全家福

    14个并发容器,你用过几个? 不考虑多线程并发的情况下,容器类一般使用ArrayList.HashMap等线程不安全的类,效率更高.在并发场景下,常会用到ConcurrentHashMap.Array ...

  6. Java多线程系列(七):并发容器的原理,7大并发容器详解、及使用场景

    之前谈过高并发编程系列: 高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 高并发编程系列:CountDownLatch.Semaphore等4大并发工具类详解 高并发编程系列:4大J ...

  7. 2019 最新蚂蚁花呗Java三面题目:红黑树+并发容器+CAS+Solr+分布式等

    蚂蚁金服专场 涵盖了蚂蚁金服从Java工程师到技术专家面试题目 支付宝高级Java三面题目:线程锁+事务+雪崩+Docker等 蚂蚁花呗团队面试题:LinkedHashMap+SpringCloud+ ...

  8. Java并发编程实战~并发容器

    在容器领域一个容易被忽视的"坑"是用迭代器遍历容器,例如在下面的代码中,通过迭代器遍历容器 list,对每个元素调用 foo() 方法,这就存在并发问题,这些组合的操作不具备原子性 ...

  9. Java 多线程 —— 常用并发容器

    引言 本博客基于常用的并发容器,简单概括其基本特性和简单使用,并不涉及较深层次的原理分析和全面的场景用法. 适合对不了解并发容器的同学,工作中遇到类似的场景,能够对文中提到的并发容器留有简单印象就好. ...

最新文章

  1. java File类笔记
  2. 【NLP】使用堆叠双向 LSTM 进行情感分析
  3. 浅谈MySQL的B树索引与索引优化
  4. 先生,要点单吗? (HTTP协议概览)
  5. ios隐藏导航栏底线条和导航、状态栏浙变色
  6. 模仿 alexa 工具条
  7. echarts 力导向图
  8. 三级网络技术--宽带接入技术--无线接入技术、光纤接入技术
  9. 如何快速区分单模与多模光纤收发器?
  10. 职称计算机 2007 还是2003,职称计算机考试, PPT2003和2007 区别大吗?哪个版本更容易。...
  11. Linux用户态进程监控内存写排查踩内存
  12. 联想计算机g480开不开机,联想G480笔记本进入不了bios怎么办_联想笔记本G480无法进入BIOS如何解决...
  13. 李炎恢-在线商城第三季总结
  14. 竞品分析——崩坏3 战双帕弥什
  15. Ubuntu下安装极点五笔输入法
  16. com.android.xiong.aysnctasktest.MainActivity$PageTask.onPostExecute(MainActivity.java:116)
  17. SMETA验厂辅导,供应商接受SEDEX验厂可以省去很多来自客户的重复审核
  18. 前端页面结构简单介绍
  19. 通过网页api接口获取网页数据
  20. Vue项目利用 i8n 实现国际化

热门文章

  1. 你对Java网络编程了解的如何?Java NIO 网络编程 | Netty前期知识(二)
  2. JVM中垃圾回收相关算法 - 值得了解一下的,因为早晚得了解
  3. matlab中如何随机排列,科学网—对图片进行拆分并随机排列的快速算法(MATLAB) - 徐磊的博文...
  4. html语言中,定义文档中一个正在打开的链接的颜色的代码是,2017微软认证考试精选练习(附答案)...
  5. 此模块的调试信息中缺少源信息_SpringBoot中的潜在漏洞分析
  6. 蓝宝石 470 原版 bios_想怎么玩就怎么玩!改造双BIOS显卡,不再为噪音和性能选择而烦恼...
  7. 无法打开 源 文件 pch.h_outlook 客户端数据文件无法打开,如何解决?
  8. windos 为什么会突然服务停止了_Windows服务异常自动关闭
  9. php mysql主从延迟_如何解决主从数据库同步延迟问题?php连接 mysql 数据库如何添加一个公共的配置文件50...
  10. 石大在线c语言在线考试填空题答案,奥鹏石大远程在线考试《钻井工程》-参考答案...