线程池可用的各种高并发容器

    科技2026-03-09  6

    目录

    1. HashTable & Vector2. ConcurrentHashMap3. ConcurrentMap4. CopyOnWrite5. LinkedBlockingQueue6. ArrayBlockingQueue7. DelayQueue8. SynchronousQueue9. TransferQueue

    1. HashTable & Vector

    HashTable实现了Map接口,Vector实现了List接口HashTable和Vector的所有方法都加了synchronized,这两个容器基本不用HashMap完全没加锁Collections类里的synchronizedMap方法会给HashMap加锁,效率和HashTable的区别不大Collections类里的synchronizedList可以给List加锁

    2. ConcurrentHashMap

    在多线程中使用的Map读数据效率很高插入数据时,java8之前使用链表,8之后使用红黑树,有很多cas的判读但,所以插入效率比较低

    3. ConcurrentMap

    ConcurrentHashMap的有序版本为使用跳表实现的ConcurrentSkipListMap

    4. CopyOnWrite

    CopyOnWriteLIst/CopyOnWriteSet写时复制:添加元素的时候,先把原容器内的元素复制,把老容器的引用指向新容器无需加锁,写的效率比较低,读的时候不用加锁,效率较高,考虑与synchronizedList的对比

    5. LinkedBlockingQueue

    无界队列put()和take() 方法实现了阻塞BlockingQueue的常用方法: poll:取数据并removepeek取数据不removeadd:添加数据,加不进去抛异常offer:添加数据,返回布尔类型

    6. ArrayBlockingQueue

    有界offer方法可以提供超时等待Queue和List的区别:Queue提供了offer、peek、poll、put、take等对线程友好的阻塞和等待方法

    7. DelayQueue

    按照等待时间排序阻塞的本质上是PriorityQueue public class DelayQueue { static BlockingQueue<MyTask> tasks = new DelayQueue<>(); static Random r = new Random(); static class MyTask implements Delayed { String name; long runningTime; MyTask(String name, long rt) { this.name = name; this.runningTime = rt; } @Override public int compareTo(Delayed o) { if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)) return -1; else if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) return 1; else return 0; } @Override public long getDelay(TimeUnit unit) { return unit.convert(runningTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public String toString() { return name + " " + runningTime; } } public static void main(String[] args) throws InterruptedException { long now = System.currentTimeMillis(); MyTask t1 = new MyTask("t1", now + 1000); MyTask t2 = new MyTask("t2", now + 2000); MyTask t3 = new MyTask("t3", now + 1500); MyTask t4 = new MyTask("t4", now + 2500); MyTask t5 = new MyTask("t5", now + 500); tasks.put(t1); tasks.put(t2); tasks.put(t3); tasks.put(t4); tasks.put(t5); System.out.println(tasks); for(int i=0; i<5; i++) { System.out.println(tasks.take()); } } }

    8. SynchronousQueue

    容量为0,不是用来装数据的,用来在两个线程之间传内容,类似Exchanger不能向队列里添加数据,只能用来阻塞式的put调用,即当存在消费者时,才可以put public class SynchronusQueue { //容量为0 public static void main(String[] args) throws InterruptedException { BlockingQueue<String> strs = new SynchronousQueue<>(); new Thread(()->{ try { System.out.println(strs.take()); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); strs.put("aaa"); //阻塞等待消费者消费 System.out.println(strs.size()); } }

    9. TransferQueue

    可以用来做线程间传递任务,与SynchronousQueue只能传递一个任务不同的是,TransferQueue可以传递多个任务当向队列中添加任务后,会进入阻塞,直到有线程将队列中的数据取走 public class TransferQueue { public static void main(String[] args) throws InterruptedException { LinkedTransferQueue<String> strs = new LinkedTransferQueue<>(); new Thread(() -> { try { System.out.println(strs.take()); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); strs.transfer("aaa"); } }
    Processed: 0.016, SQL: 9