6 并发编程之并发集合类

在 Java 的并发编程中,传统的集合类如 ArrayListHashMap 并不安全,无法在多线程环境中保证数据的一致性和安全性。为了满足并发环境下的数据操作需求,Java 提供了一系列并发集合类,这些类在 java.util.concurrent 包中定义。本篇文章将详细介绍这些并发集合类,帮助你在并发编程中更好地管理数据。

1. 为什么需要并发集合类?

在多线程环境下,多个线程可以同时访问和修改共享数据,这就可能导致数据的不一致或错误。并发集合类通过内部的同步机制,使得多个线程在访问集合时能够安全地进行操作。

2. 常用的并发集合类

2.1 ConcurrentHashMap

ConcurrentHashMap 是一个线程安全的哈希表,允许并发读取和更新操作。它使用了一种分段锁定的机制来提高性能。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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 < 10; i++) {
map.put(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("Final map: " + map);
}
}

2.2 CopyOnWriteArrayList

CopyOnWriteArrayList 是一个线程安全的变体,可以在写操作时进行复制操作,提高了读取的性能。适用于读多写少的场景。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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");

// 创建多个线程来并发读取和更新集合
Runnable task = () -> {
for (int i = 0; i < 5; i++) {
list.add(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("Final list: " + list);
}
}

2.3 BlockingQueue

BlockingQueue 接口有多种实现,例如 ArrayBlockingQueueLinkedBlockingQueue,这些队列可以在并发生产者-消费者模型中扮演重要角色。它们支持阻塞操作,如当队列为空时,消费者线程会被阻塞,直到有新元素可用。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.concurrent.ArrayBlockingQueue;

public class BlockingQueueExample {
public static void main(String[] args) {
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);

// 生产者线程
Runnable producer = () -> {
for (int i = 0; i < 10; i++) {
try {
queue.put(i);
System.out.println("Produced: " + i);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};

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

Thread producerThread = new Thread(producer);
Thread consumerThread = new Thread(consumer);

producerThread.start();
consumerThread.start();

// 等待线程结束
try {
producerThread.join();
consumerThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

3. 总结

在并发编程中,选择合适的并发集合类对于保证数据安全与提高性能至关重要。通过上面几种集合类的学习,我们可以看到它们在多线程环境中的优势和适用场景。

在本文中,我们重点介绍了 ConcurrentHashMapCopyOnWriteArrayListBlockingQueue,这些都是进行高效并发编程时常用的工具。接下来,我们将会学习 Java 8 的新特性之一,即 Lambda 表达式,这一特性将使得我们的代码更加简洁和易于维护。

6 并发编程之并发集合类

https://zglg.work/java-one/6/

作者

IT教程网(郭震)

发布于

2024-08-10

更新于

2024-08-10

许可协议

分享转发

学习下节

交流

更多教程加公众号

更多教程加公众号

加入星球获取PDF

加入星球获取PDF

打卡评论