Java - 并发容器

92 阅读3分钟

并发容器概述

Java 提供了一系列并发容器,位于 java.util.concurrent 包中,旨在支持多线程环境下的安全和高效的数据结构操作。与常规集合相比,并发容器能够在多个线程同时访问时提供更好的性能和更高的安全性。以下是一些常用的并发容器及其特点:

1. ConcurrentHashMap

ConcurrentHashMap 是一种线程安全的哈希表实现,允许多个线程同时读和写。其主要特点包括:

  • 分段锁定:通过将数据分段并为每个段加锁,允许多个线程并发访问。
  • 高效的读取:读取操作不需要加锁,性能较高。
  • 支持 null 值:允许存储 null 值(与 Hashtable 不同)。

示例:

java
复制代码
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
        
        map.put("A", 1);
        map.put("B", 2);
        
        // 并发更新
        map.compute("A", (key, val) -> val + 1);
        System.out.println(map.get("A")); // 输出 2
    }
}
2. CopyOnWriteArrayList

CopyOnWriteArrayList 是一个线程安全的变体,它在写操作时创建底层数组的一个副本。这使得读操作可以在不加锁的情况下进行,适合读多写少的场景。

  • 写时复制:每次写操作都会复制数组,这样可以避免并发读时的干扰。
  • 快速迭代:由于读取不会加锁,可以高效地进行迭代操作。

示例:

java
复制代码
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListExample {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        
        list.add("A");
        list.add("B");
        
        // 迭代
        for (String item : list) {
            System.out.println(item); // 输出 A 和 B
        }
        
        // 添加新元素
        list.add("C");
    }
}
3. BlockingQueue

BlockingQueue 接口及其实现(如 ArrayBlockingQueueLinkedBlockingQueue 等)提供了线程安全的队列实现,支持阻塞的插入和移除操作。

  • 生产者-消费者模式:适合实现生产者-消费者问题,支持线程间的协作。
  • 阻塞特性:当队列满时,插入操作会阻塞;当队列空时,移除操作会阻塞。

示例:

java
复制代码
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueExample {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
        
        // 生产者线程
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    queue.put("Item " + i);
                    System.out.println("Produced: Item " + i);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        // 消费者线程
        Thread consumer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    String item = queue.take();
                    System.out.println("Consumed: " + item);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        producer.start();
        consumer.start();
        
        producer.join();
        consumer.join();
    }
}
4. ConcurrentSkipListMap

ConcurrentSkipListMap 是一种线程安全的有序映射,底层使用跳表实现。它提供了按键排序的能力,并支持高效的并发访问。

  • 无锁算法:通过无锁算法实现高效的插入、删除和查找操作。
  • 排序访问:可以按照自然顺序或指定的比较器进行遍历。

示例:

java
复制代码
import java.util.concurrent.ConcurrentSkipListMap;

public class ConcurrentSkipListMapExample {
    public static void main(String[] args) {
        ConcurrentSkipListMap<Integer, String> skipListMap = new ConcurrentSkipListMap<>();
        
        skipListMap.put(2, "B");
        skipListMap.put(1, "A");
        
        // 遍历
        skipListMap.forEach((key, value) -> System.out.println(key + ": " + value));
        // 输出 1: A 和 2: B
    }
}

总结

Java 的并发容器提供了线程安全的集合实现,适用于多线程环境。选择合适的并发容器可以提高程序的性能和可靠性。在使用时,需要根据具体的应用场景和需求来选择合适的容器类型。