java并发容器类

冷不防 2021-10-14 05:16 720阅读 0赞

一、概述

  1. Java中,普通常用集合

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1MTUxMzQ2_size_16_color_FFFFFF_t_701.这些集合在我们编程中经常用到,但是在这些集合中除HashTale外,其他的都是属于线程不安全的,意味着我们在多线程情况下使用这些集合,我们的数据不能得到保障。单是HashTable的底层实现是给整个数组加了一把锁,意味着在多线程下,势必会出现线程竞争资源的情况,轻量级锁不停自旋后会升级为重量级锁,性能较差。

2.为了能够在多线程情况下操作数据,java在J.U.C包下提供了一些并发容器类供我们操作,

二、并发容器

一、结构图

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1MTUxMzQ2_size_16_color_FFFFFF_t_70 1

二、ConcurrentHashMap

  1. 1.jdk1.8之前,HashTable采用的结构是给整个数组上锁,而ConcurrentHashMap采用的则是分段锁,将一个数组分成很多个segment,在jdk1.8之后,放弃了分段锁的这种方式,而是使用底层数据结构和hashMap一样的数组+链表+红黑树。

  2.在一个桶中,如果node节点的个数大于8之后,就会将原本链表的结构转换成红黑树,红黑树查找数据的时间复杂度为树的深度,即O(logn),在node节点的个数小于6之后,又会将红黑树的结构转化成链表,同时使用了unsafe类,即一些CAS操作。

  3.基本使用

  1. package com.test;
  2. import java.util.concurrent.ConcurrentHashMap;
  3. /**
  4. *线程类,往map里面存放数据,存放一个数据休眠时间20毫秒
  5. */
  6. public class PuThread implements Runnable{
  7. private ConcurrentHashMap<String,String> map;
  8. public PuThread(ConcurrentHashMap<String,String> map){
  9. this.map=map;
  10. }
  11. public void run() {
  12. for(int i=0;i<10;i++){
  13. try {
  14. Thread.sleep(20);
  15. } catch (InterruptedException e) {
  16. e.printStackTrace();
  17. }
  18. map.put(String.valueOf(i), String.valueOf(i));
  19. }
  20. }
  21. }

一个线程用来存放数据,为了模拟在多线程下操作数据,我们同时创建了另外一个线程来存放数据

 

  1. package com.test;
  2. import java.util.concurrent.ConcurrentHashMap;
  3. /**
  4. *线程类,往map里面存放数据,存放一个数据休眠时间20毫秒
  5. */
  6. public class PuThread2 implements Runnable{
  7. private ConcurrentHashMap<String,String> map;
  8. public PuThread2(ConcurrentHashMap<String,String> map){
  9. this.map=map;
  10. }
  11. public void run() {
  12. for(int i=10;i<20;i++){
  13. try {
  14. Thread.sleep(20);
  15. } catch (InterruptedException e) {
  16. e.printStackTrace();
  17. }
  18. map.put(String.valueOf(i), String.valueOf(i));
  19. }
  20. }
  21. }

最后又创建了一个线程用来读取里面的数据

  1. package com.test;
  2. import java.util.concurrent.ConcurrentHashMap;
  3. public class GeThread implements Runnable{
  4. private ConcurrentHashMap<String,String> map;
  5. public GeThread(ConcurrentHashMap<String,String> map){
  6. this.map=map;
  7. }
  8. public void run() {
  9. for(int i=0;i<20;i++){
  10. try {
  11. Thread.sleep(20);
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. System.out.println(map.get(String.valueOf(i)));
  16. }
  17. }
  18. }

#

来看下主方法

  1. public class Test1 {
  2. public static void main(String[] args) {
  3. System.out.println("开始");
  4. currentHash();
  5. }
  6. public static void currentHash(){
  7. ConcurrentHashMap<String, String> map=new ConcurrentHashMap<String, String>();
  8. System.out.println("开始");
  9. map.put("aa", "aa");
  10. map.put("bb", "bb");
  11. map.put("cc", "cc");
  12. map.put("dd", "dd");
  13. map.put("ee", "ee");
  14. Thread pu=new Thread(new PuThread(map));
  15. Thread pu2=new Thread(new PuThread2(map));
  16. Thread ge=new Thread(new GeThread(map));
  17. pu.start();
  18. pu2.start();
  19. ge.start();
  20. System.out.println(map.toString());
  21. }
  22. }

三、CopyOnWriteArrayList

 1.实现了list接口,底层使用的是可重入锁,ReentrantLock

  1. /** The lock protecting all mutators */
  2. final transient ReentrantLock lock = new ReentrantLock();

  2.加锁位置,在设置元素时加了锁。

  1. **
  2. * Replaces the element at the specified position in this list with the
  3. * specified element.
  4. *
  5. * @throws IndexOutOfBoundsException {@inheritDoc}
  6. */
  7. public E set(int index, E element) {
  8. final ReentrantLock lock = this.lock;
  9. lock.lock();
  10. try {
  11. Object[] elements = getArray();
  12. E oldValue = get(elements, index);
  13. if (oldValue != element) {
  14. int len = elements.length;
  15. Object[] newElements = Arrays.copyOf(elements, len);
  16. newElements[index] = element;
  17. setArray(newElements);
  18. } else {
  19. // Not quite a no-op; ensures volatile write semantics
  20. setArray(elements);
  21. }
  22. return oldValue;
  23. } finally {
  24. lock.unlock();
  25. }
  26. }

3.同时我们可以发现在get方法(即读的时候)并没有加锁

  1. /**
  2. * {@inheritDoc}
  3. *
  4. * @throws IndexOutOfBoundsException {@inheritDoc}
  5. */
  6. public E get(int index) {
  7. return get(getArray(), index);
  8. }

4.所以CopyOnWriteArrayList支持读多写少的情况

四、ArrayBlockingQueue

1.数组实现的有界队列

五、LinkedBlockingQueue

1.LinkedBlockingQueue如果不手动指定容量,那么的他的容量将为Integer.MAX_VALUE

六、SynchronousQueue

发表评论

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

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

相关阅读

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

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

    相关 并发容器

    并发类容器 JDK 1.5之后,提供了多种并发类容器 来代替同步类容器,改善性能 同步类容器 状态都是串行化的,虽然,实现了线程安全 但是,严重降低了并发性