解决并发情况下的容器线程安全问题的。给多线程环境准备一个线程安全的容器对象。
  线程安全的容器对象: Vector, Hashtable。线程安全容器对象,都是使用 synchronized 方法实现的。
  concurrent 包中的同步容器,大多数是使用系统底层技术实现的线程安全。类似 native。 Java8 中使用 CAS。

1、Map/Set

  1.1 ConcurrentHashMap/ConcurrentHashSet

    底层哈希实现的同步 Map(Set)。效率高,线程安全。使用系统底层技术实现线程安全。 量级较 synchronized 低。key 和 value 不能为 null。

  1.2 ConcurrentSkipListMap/ConcurrentSkipListSet

    底层跳表(SkipList)实现的同步 Map(Set)。有序,效率比 ConcurrentHashMap 稍低。

  1. import java.util.Map;
  2. import java.util.Random;
  3. import java.util.concurrent.ConcurrentHashMap;
  4. import java.util.concurrent.CountDownLatch;
  5.  
  6. public class Test_01_ConcurrentMap {
  7.  
  8. public static void main(String[] args) {
  9. // final Map<String, String> map = new Hashtable<>();
  10. final Map<String, String> map = new ConcurrentHashMap<>();
  11. //ConcurrentSkipListMap跳表实现的,是排序的,最慢
  12. // final Map<String, String> map = new ConcurrentSkipListMap<>();
  13. final Random r = new Random();
  14. Thread[] array = new Thread[100];
  15. final CountDownLatch latch = new CountDownLatch(array.length);
  16.  
  17. long begin = System.currentTimeMillis();
  18. for (int i = 0; i < array.length; i++) {
  19. array[i] = new Thread(new Runnable() {
  20. @Override
  21. public void run() {
  22. for (int j = 0; j < 100000; j++) {
  23. map.put("key" + r.nextInt(100000), "value" + r.nextInt(100000));
  24. }
  25. latch.countDown();
  26. }
  27. });
  28. }
  29. for (Thread t : array) {
  30. t.start();
  31. }
  32. try {
  33. latch.await();
  34. } catch (InterruptedException e) {
  35. e.printStackTrace();
  36. }
  37. long end = System.currentTimeMillis();
  38. System.out.println("执行时间为 : " + (end - begin) + "毫秒!");
  39. }
  40.  
  41. }

2、List

  2.1 CopyOnWriteArrayList

    写时复制集合。写入效率低,读取效率高。每次写入数据,都会创建一个新的底层数组。

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import java.util.Random;
  4. import java.util.concurrent.CountDownLatch;
  5.  
  6. public class Test_02_CopyOnWriteList {
  7.  
  8. public static void main(String[] args) {
  9. final List<String> list = new ArrayList<>();
  10. // final List<String> list = new Vector<>();
  11. // final List<String> list = new CopyOnWriteArrayList<>();
  12. final Random r = new Random();
  13. Thread[] array = new Thread[100];
  14. final CountDownLatch latch = new CountDownLatch(array.length);
  15.  
  16. long begin = System.currentTimeMillis();
  17. for (int i = 0; i < array.length; i++) {
  18. array[i] = new Thread(new Runnable() {
  19. @Override
  20. public void run() {
  21. for (int j = 0; j < 1000; j++) {
  22. list.add("value" + r.nextInt(100000));
  23. }
  24. latch.countDown();
  25. }
  26. });
  27. }
  28. for (Thread t : array) {
  29. t.start();
  30. }
  31. try {
  32. latch.await();
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. }
  36. long end = System.currentTimeMillis();
  37. System.out.println("执行时间为 : " + (end - begin) + "毫秒!");
  38. System.out.println("List.size() : " + list.size());
  39. }
  40.  
  41. }

3、Queue

  3.1 ConcurrentLinkedQueue

    基础链表同步队列。

  1. /**
  2. * 并发容器 - ConcurrentLinkedQueue
  3. * 队列 - 链表实现的。
  4. */
  5. import java.util.Queue;
  6. import java.util.concurrent.ConcurrentLinkedQueue;
  7.  
  8. public class Test_03_ConcurrentLinkedQueue {
  9.  
  10. public static void main(String[] args) {
  11. Queue<String> queue = new ConcurrentLinkedQueue<>();
  12. for (int i = 0; i < 10; i++) {
  13. queue.offer("value" + i);
  14. }
  15.  
  16. System.out.println(queue);
  17. System.out.println(queue.size());
  18.  
  19. // peek() -> 查看queue中的首数据
  20. System.out.println(queue.peek());
  21. System.out.println(queue.size());
  22.  
  23. // poll() -> 获取queue中的首数据
  24. System.out.println(queue.poll());
  25. System.out.println(queue.size());
  26. }
  27.  
  28. }

  3.2 LinkedBlockingQueue

    阻塞队列,队列容量不足自动阻塞,队列容量为 0 自动阻塞。

  1. /**
  2. * 并发容器 - LinkedBlockingQueue
  3. * 阻塞容器。
  4. * put & take - 自动阻塞。
  5. * put自动阻塞, 队列容量满后,自动阻塞
  6. * take自动阻塞方法, 队列容量为0后,自动阻塞。
  7. */
  8.  
  9. import java.util.Random;
  10. import java.util.concurrent.BlockingQueue;
  11. import java.util.concurrent.LinkedBlockingQueue;
  12. import java.util.concurrent.TimeUnit;
  13.  
  14. public class Test_04_LinkedBlockingQueue {
  15.  
  16. final BlockingQueue<String> queue = new LinkedBlockingQueue<>();
  17. final Random r = new Random();
  18.  
  19. public static void main(String[] args) {
  20. final Test_04_LinkedBlockingQueue t = new Test_04_LinkedBlockingQueue();
  21.  
  22. new Thread(new Runnable() {
  23. @Override
  24. public void run() {
  25. while (true) {
  26. try {
  27. t.queue.put("value" + t.r.nextInt(1000));
  28. TimeUnit.SECONDS.sleep(1);
  29. } catch (InterruptedException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }
  34. }, "producer").start();
  35.  
  36. for (int i = 0; i < 3; i++) {
  37. new Thread(new Runnable() {
  38. @Override
  39. public void run() {
  40. while (true) {
  41. try {
  42. System.out.println(Thread.currentThread().getName() +
  43. " - " + t.queue.take());
  44. } catch (InterruptedException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. }
  49. }, "consumer" + i).start();
  50. }
  51. }
  52.  
  53. }

  3.3 ArrayBlockingQueue

    底层数组实现的有界队列。自动阻塞。根据调用 API(add/put/offer)不同,有不同特 性。
    当容量不足的时候,有阻塞能力。
    add 方法在容量不足的时候,抛出异常put 方法在容量不足的时候,阻塞等待
    offer 方法:
    单参数 offer 方法,不阻塞。容量不足的时候,返回 false。当前新增数据操作放弃。 三参数 offer 方法(offer(value,times,timeunit)),容量不足的时候,阻塞 times 时长(单
位为 timeunit),如果在阻塞时长内,有容量空闲,新增数据返回 true。如果阻塞时长范围 内,无容量空闲,放弃新增数据,返回 false。

  1. /**
  2. * 并发容器 - ArrayBlockingQueue
  3. * 有界容器。
  4. */
  5.  
  6. import java.util.concurrent.ArrayBlockingQueue;
  7. import java.util.concurrent.BlockingQueue;
  8. import java.util.concurrent.TimeUnit;
  9.  
  10. public class Test_05_ArrayBlockingQueue {
  11.  
  12. final BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
  13.  
  14. public static void main(String[] args) {
  15. final Test_05_ArrayBlockingQueue t = new Test_05_ArrayBlockingQueue();
  16.  
  17. for (int i = 0; i < 5; i++) {
  18. // System.out.println("add method : " + t.queue.add("value"+i));
  19. /*try {
  20. t.queue.put("put"+i);
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. System.out.println("put method : " + i);*/
  25. // System.out.println("offer method : " + t.queue.offer("value"+i));
  26. try {
  27. System.out.println("offer method : " +
  28. t.queue.offer("value" + i, 1, TimeUnit.SECONDS));
  29. } catch (InterruptedException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33.  
  34. System.out.println(t.queue);
  35. }
  36.  
  37. }

  3.4 DelayQueue

    延时队列。根据比较机制,实现自定义处理顺序的队列。常用于定时任务。
    如:定时关机。

  1. /**
  2. * 并发容器 - DelayQueue
  3. * 无界容器。
  4. */
  5.  
  6. import java.util.concurrent.BlockingQueue;
  7. import java.util.concurrent.DelayQueue;
  8. import java.util.concurrent.Delayed;
  9. import java.util.concurrent.TimeUnit;
  10.  
  11. public class Test_06_DelayQueue {
  12.  
  13. static BlockingQueue<MyTask_06> queue = new DelayQueue<>();
  14.  
  15. public static void main(String[] args) throws InterruptedException {
  16. long value = System.currentTimeMillis();
  17. MyTask_06 task1 = new MyTask_06(value + 2000);
  18. MyTask_06 task2 = new MyTask_06(value + 1000);
  19. MyTask_06 task3 = new MyTask_06(value + 3000);
  20. MyTask_06 task4 = new MyTask_06(value + 2500);
  21. MyTask_06 task5 = new MyTask_06(value + 1500);
  22.  
  23. queue.put(task1);
  24. queue.put(task2);
  25. queue.put(task3);
  26. queue.put(task4);
  27. queue.put(task5);
  28.  
  29. System.out.println(queue);
  30. System.out.println(value);
  31. for (int i = 0; i < 5; i++) {
  32. System.out.println(queue.take());
  33. }
  34. }
  35.  
  36. }
  37.  
  38. class MyTask_06 implements Delayed {
  39.  
  40. private long compareValue;
  41.  
  42. public MyTask_06(long compareValue) {
  43. this.compareValue = compareValue;
  44. }
  45.  
  46. /**
  47. * 比较大小。自动实现升序
  48. * 建议和getDelay方法配合完成。
  49. * 如果在DelayQueue是需要按时间完成的计划任务,必须配合getDelay方法完成。
  50. */
  51. @Override
  52. public int compareTo(Delayed o) {
  53. return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
  54. }
  55.  
  56. /**
  57. * 获取计划时长的方法。
  58. * 根据参数TimeUnit来决定,如何返回结果值。
  59. */
  60. @Override
  61. public long getDelay(TimeUnit unit) {
  62. return unit.convert(compareValue - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
  63. }
  64.  
  65. @Override
  66. public String toString() {
  67. return "Task compare value is : " + this.compareValue;
  68. }
  69.  
  70. }

  3.5 LinkedTransferQueue

    转移队列,是一个容量为 0 的队列。使用 transfer 方法,实现数据的即时处理。没有消费者,就阻塞。

  1. /**
  2. * 并发容器 - LinkedTransferQueue
  3. * 转移队列
  4. * add - 队列会保存数据,不做阻塞等待。
  5. * transfer - 是TransferQueue的特有方法。必须有消费者(take()方法的调用者)。
  6. * 如果没有任意线程消费数据,transfer方法阻塞。一般用于处理即时消息。
  7. */
  8.  
  9. import java.util.concurrent.LinkedTransferQueue;
  10. import java.util.concurrent.TimeUnit;
  11. import java.util.concurrent.TransferQueue;
  12.  
  13. public class Test_07_TransferQueue {
  14.  
  15. TransferQueue<String> queue = new LinkedTransferQueue<>();
  16.  
  17. public static void main(String[] args) {
  18. final Test_07_TransferQueue t = new Test_07_TransferQueue();
  19.  
  20. /*new Thread(new Runnable() {
  21. @Override
  22. public void run() {
  23. try {
  24. System.out.println(Thread.currentThread().getName() + " thread begin " );
  25. System.out.println(Thread.currentThread().getName() + " - " + t.queue.take());
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }, "output thread").start();
  31.  
  32. try {
  33. TimeUnit.SECONDS.sleep(2);
  34. } catch (InterruptedException e) {
  35. e.printStackTrace();
  36. }
  37.  
  38. try {
  39. t.queue.transfer("test string");
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. }*/
  43.  
  44. new Thread(new Runnable() {
  45.  
  46. @Override
  47. public void run() {
  48. try {
  49. t.queue.transfer("test string");
  50. // t.queue.add("test string");
  51. System.out.println("add ok");
  52. } catch (Exception e) {
  53. e.printStackTrace();
  54. }
  55. }
  56. }).start();
  57.  
  58. try {
  59. TimeUnit.SECONDS.sleep(2);
  60. } catch (InterruptedException e) {
  61. e.printStackTrace();
  62. }
  63.  
  64. new Thread(new Runnable() {
  65. @Override
  66. public void run() {
  67. try {
  68. System.out.println(Thread.currentThread().getName() + " thread begin ");
  69. System.out.println(Thread.currentThread().getName() + " - " + t.queue.take());
  70. } catch (InterruptedException e) {
  71. e.printStackTrace();
  72. }
  73. }
  74. }, "output thread").start();
  75.  
  76. }
  77.  
  78. }

  3.6 SynchronusQueue

    同步队列,是一个容量为 0 的队列。是一个特殊的 TransferQueue。 必须现有消费线程等待,才能使用的队列。
    add 方法,无阻塞。若没有消费线程阻塞等待数据,则抛出异常。 put 方法,有阻塞。若没有消费线程阻塞等待数据,则阻塞。

  1. /**
  2. * 并发容器 - SynchronousQueue
  3. */
  4. import java.util.concurrent.BlockingQueue;
  5. import java.util.concurrent.SynchronousQueue;
  6. import java.util.concurrent.TimeUnit;
  7.  
  8. public class Test_08_SynchronusQueue {
  9.  
  10. BlockingQueue<String> queue = new SynchronousQueue<>();
  11.  
  12. public static void main(String[] args) {
  13. final Test_08_SynchronusQueue t = new Test_08_SynchronusQueue();
  14.  
  15. new Thread(new Runnable() {
  16. @Override
  17. public void run() {
  18. try {
  19. System.out.println(Thread.currentThread().getName() + " thread begin ");
  20. try {
  21. TimeUnit.SECONDS.sleep(2);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. System.out.println(Thread.currentThread().getName() + " - " + t.queue.take());
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }, "output thread").start();
  31.  
  32. /*try {
  33. TimeUnit.SECONDS.sleep(3);
  34. } catch (InterruptedException e) {
  35. e.printStackTrace();
  36. }*/
  37. // t.queue.add("test add");
  38. try {
  39. t.queue.put("test put");
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. }
  43.  
  44. System.out.println(Thread.currentThread().getName() + " queue size : " + t.queue.size());
  45. }
  46.  
  47. }

Java并发编程之并发容器的更多相关文章

  1. Java并发编程:同步容器

    Java并发编程:同步容器 为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch). ...

  2. Java并发编程:并发容器ConcurrentHashMap

    Java并发编程:并发容器之ConcurrentHashMap(转载) 下面这部分内容转载自: http://www.haogongju.net/art/2350374 JDK5中添加了新的concu ...

  3. 【转】Java并发编程:同步容器

    为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch).今天我们就来讨论下同步容器. ...

  4. 8、Java并发编程:同步容器

    Java并发编程:同步容器 为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch). ...

  5. Java并发编程:并发容器之CopyOnWriteArrayList(转载)

    Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...

  6. Java并发编程:并发容器之ConcurrentHashMap(转载)

    Java并发编程:并发容器之ConcurrentHashMap(转载) 下面这部分内容转载自: http://www.haogongju.net/art/2350374 JDK5中添加了新的concu ...

  7. Java并发编程:并发容器之ConcurrentHashMap

    转载: Java并发编程:并发容器之ConcurrentHashMap JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的 ...

  8. Java并发编程:并发容器之CopyOnWriteArrayList

    转载: Java并发编程:并发容器之CopyOnWriteArrayList Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个 ...

  9. 【转】Java并发编程:并发容器之CopyOnWriteArrayList

    Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...

  10. 【转】Java并发编程:并发容器之ConcurrentHashMap

    JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以这种方法的代价就是严重降低了 ...

随机推荐

  1. 如何让SQLServer的 itemNum 字段 按照数字大小顺序排序

    我的 itemNum 从1到20,可是超过了SQLServer的默认排序这样的1101112...19234567如何才能让排序成为这样1234567891011.. . 解决办法:因为 itemNu ...

  2. Ubuntu下安装Snap

    介绍 Snap是一个全新的软件包架构,它与其它包管理器的区别在于snap安装的app互相之间是高度隔离的,减少了互相引用. 避免了很多冲突问题. 不过这也导致了其占用的磁盘比较多. 安装 apt in ...

  3. 搭建zookeeper+kafka集群

      搭建zookeeper+kafka集群 一.环境及准备 集群环境:   软件版本: 部署前操作: 关闭防火墙,关闭selinux(生产环境按需关闭或打开) 同步服务器时间,选择公网ntpd服务器或 ...

  4. java类的生命周期

    https://www.cnblogs.com/aspirant/p/7200523.html 验证的内容:文件格式,字节码,符号引用,元数据 准备:给静态变量分配内存设置初始值(0) 初始化才是真正 ...

  5. Oracle数据库中OVER()函数的了解

    1.over函数介绍:      开窗函数,Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行. ...

  6. [C#]位运算符

    参考链接: http://www.runoob.com/csharp/csharp-operators.html 表: 简单来说,就是: &:全1为1,否则为0 |:有1为1,否则为0 ^:不 ...

  7. 06 Jquery 基础

    前端学习之jquery: jQuery:一个库 Jquery的基础语法: $(selector).action() 基本选择器: <script> //基本选择器 //$("*& ...

  8. C#对象与XMl文件之间的相互转换(转)

    本文是对C#中对象与XMl文件之间的相互转换进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 C#提供三种序列化方式,分别为:1.是使用BinaryFormatter进行串行化: 2.使 ...

  9. django原生sql查询如何返回字典格式

    django原生sql查询,默认返回的是元祖.如果想返回字典格式,需要自行封装: http://www.360doc.com/content/17/0802/11/9200790_676042880. ...

  10. JS写一个简单日历

    JS写一个日历,配合jQuery操作DOM <!DOCTYPE html> <html> <head> <meta charset="UTF-8&q ...