JAVA并发容器

本文探讨了Java中不同并发容器的特性与使用场景,包括HashMap、HashTable与CurrentHashMap,ArrayList、Vector与CurrentLinkQueue。重点讲解了HashMap与CurrentHashMap在并发环境下的效率差异,以及ArrayList、Vector与CurrentLinkQueue的线程安全性。还介绍了高并发环境下推荐使用的容器,如ConcurrentHashMap、CopyOnWriteArrayList、Queue等,并详细列举了各种Queue的方法及其行为。最后提到了特殊的队列类型,如SynchronizedQueue、LinkedTransferQueue等,它们在任务调度中的作用。

在这里插入图片描述
面试题一:List和Queue的区别?
Queue添加了这些对线程友好的API,offer(),peek(),poll();BlockQueue额外添加了put(),take()api,实现阻塞


1.容器分成两类Collection和Map
2.Queue专门为高并发做准备的

一、HashMap,HashTable,CurrentHashmap

HashMap,是线程不安全的
HashTable,线程安全的,使用synchronized锁,效率低
CurrentHashMap,线程安全的,推荐使用

HashTable,Collections.sychronizedMap,CurrentHashMap插入、查询效率比较
插入效率:CurrentHashMap最慢,因为涉及链表和红黑树
查询效率:CurrentHashMap最快

二、ArrayList,Vector,CurrentLinkQueue

ArrayList,是线程不安全的
Vector,是线程安全,使用synchronized锁,效率低
CurrentLinkQueue,是线程安全的,推荐使用,使用CAS来加锁
多线程程序,在使用容器时,推荐使用Queue

    Queue<String> queue = new ConcurrentLinkedQueue<>();
        queue.poll();
        
ConcurrentLinkedQueue源码
   boolean casItem(E cmp, E val) {
            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);//可以看出使用CAS锁
        }

三、常用高并发容器

1.ConcurrentHashMap
2.ConcurrentSkipListMap //高并发并且排序,代替treeMap
调表:把一些关键元素抽取到另外一行,查找时从上往下查找
在这里插入图片描述
3.CopyOnWriteArrayList 读的量大,写的量小 (写加锁,读不用加锁)

源码:CopyOnWriteArrayList.java
写操作
1.加锁
2.copy一个新的数组
3.把值写入新的数据
4.把新的数据赋值到原来的引用上
读操作
1.不用加锁,直接读取(因为新的部分,与老的内容一摸一样)

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();
        }
    }
 public E get(int index) {
        return get(getArray(), index);
    }

4.Queue
常用方法
add();// 加不进去,会抛异常
offer()//通过返回值,判断是否加进去
poll();//获取值,并且remove
peek()//获取值,但是不会remove

5.BlockQueue
put();//如果满了,则这个线程会阻塞
take();//如果拿完了,则这个线程阻塞

6.LinkedBlockingQueue 无界的阻塞队列

源码: LinkedBlockingQueue.java
1.put会阻塞,是通过notFull.await()实现的阻塞
2.condition.await()底层是通过 LockSupport.park来实现的阻塞

public void put(E e) throws InterruptedException {
        putLast(e);
    }

   public void putLast(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        Node<E> node = new Node<E>(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            while (!linkLast(node))
                notFull.await();
        } finally {
            lock.unlock();
        }
    }

7.ArrayBlockingQueue 有界的阻塞队列
8.PriorityQueue 排序队列,内部使用二叉树排序
9.DelayQueue 按照时间上排序的队列;按时间进行任务调度
本质是使用PriorityQueue进去排序的

10.SynchronizedQueue 容量为0的queue,传递任务的队列
这个queue不能存放任何数据,除非前面有一个人获取,才可以往里面装数据(直接从一个线程把数据拿给另外一个线程,可以理解为这个queue不存在,相当于两个线程交换数据)。JUC中线程调度很多时候就是用的这个SynchronizedQueue

//特殊的transferQueue
BlockingQueue<String> strs = new SynchronousQueue<>();
strs.take();
strs.put("aa");//阻塞等待消费者消费,内部就是transfer()

11.LinkedTransferQueue
transfer(): 把数据写入后会阻塞,直到这个数据被取走
场景:用户下了订单,这个订单会进入tranferQueue队列,直到这个订单被处理了,我才告诉用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值