接下来我们学习第七部分:Java 的并发集合。
7. Java 的并发集合
Java 提供了一系列并发集合类,位于 java.util.concurrent
包中。这些集合类为多线程环境下的数据共享和管理提供了安全的解决方案。相比于传统的集合类,它们支持更高效的并发操作,避免了显式的同步。
7.1 ConcurrentHashMap
ConcurrentHashMap
是一个线程安全的哈希表,支持高并发的读写操作。它通过将数据分段来实现高效的并发访问。
特性
- 分段锁:将整个表分成多个段,允许多个线程同时访问不同的段。
- 高效的读取:读操作不会加锁,保证了高并发读取的性能。
- 支持
null
键和null
值:不同于Hashtable
,ConcurrentHashMap
允许null
键和值。
示例代码
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);
// 创建线程执行并发操作
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
map.put("A", map.get("A") + 1);
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final value of A: " + map.get("A")); // 期待值大于2000
}
}
7.2 CopyOnWriteArrayList
CopyOnWriteArrayList
是一个线程安全的列表实现。它的主要特点是在修改操作时,会创建一个新的数组副本,从而保证读操作的安全。
特性
- 写时复制:每次修改都会创建一个新的数组,保证了读操作不受影响。
- 高效的读操作:读操作是无锁的,非常高效。
- 适用于读多写少的场景。
示例代码
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
// 向集合中添加数据
list.add("A");
list.add("B");
// 创建线程执行并发操作
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
list.add("C");
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Size of list: " + list.size()); // 期待值大于2000
}
}
7.3 BlockingQueue
接口
BlockingQueue
是一个支持阻塞操作的队列接口,允许多个线程安全地操作队列。它提供了丰富的方法来实现生产者-消费者模式。
常用实现
ArrayBlockingQueue
:有界阻塞队列,使用数组实现,支持 FIFO(先进先出)顺序。LinkedBlockingQueue
:可选择有界或无界的阻塞队列,使用链表实现。PriorityBlockingQueue
:支持优先级排序的阻塞队列。
示例代码(生产者-消费者模式)
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProducerConsumerExample {
private static final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5); // 有界队列,容量5
public static void main(String[] args) {
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
queue.put(i); // 阻塞添加元素
System.out.println("Produced: " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
int value = queue.take(); // 阻塞获取元素
System.out.println("Consumed: " + value);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
producer.start();
consumer.start();
try {
producer.join();
consumer.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
7.4 ConcurrentLinkedQueue
ConcurrentLinkedQueue
是一个无界线程安全的队列实现,采用非阻塞算法实现。
特性
- 高并发:适用于大量线程同时访问的场景。
- 无界:队列的大小仅受系统内存限制。
示例代码
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
// 创建线程执行并发操作
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
queue.offer(Thread.currentThread().getName() + " - " + i); // 添加元素
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Queue size: " + queue.size()); // 期待值为2000
}
}
总结
Java 的并发集合提供了多种高效、安全的集合类,以支持在多线程环境下的数据共享和管理。了解这些集合类的特性和使用场景,能够帮助我们更好地开发并发应用。
下一步,我们将学习 Java 中的并发设计模式,包括一些常见的设计模式及其在并发编程中的应用。