您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Java中并发容器J.U.C怎么用
## 一、J.U.C概述
Java并发工具包(Java Util Concurrent,简称J.U.C)是Java 5引入的一组高质量并发编程工具,位于`java.util.concurrent`包下。它提供了比传统同步容器更高效的线程安全实现,主要包含以下组件:
1. **并发集合**:替代同步集合的高性能线程安全容器
2. **同步器**:如CountDownLatch、CyclicBarrier等
3. **线程池**:Executor框架
4. **原子变量**:AtomicInteger等
5. **锁机制**:ReentrantLock等
## 二、核心并发容器详解
### 1. ConcurrentHashMap
#### 基本用法
```java
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("key1", 1);
map.putIfAbsent("key1", 2); // 不存在才放入
int value = map.get("key1");
// 原子更新
map.compute("key1", (k, v) -> v == null ? 1 : v + 1);
// 搜索
String result = map.search(1, (k, v) -> v > 100 ? k : null);
// 批量操作
map.forEach(2, (k, v) -> System.out.println(k + ":" + v));
读多写少的并发场景,如事件监听器列表
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("item1"); // 写时复制
String item = list.get(0); // 无锁读取
无界非阻塞队列实现:
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("element1");
String head = queue.poll();
特点: - CAS实现的无锁算法 - 高性能但size()方法需要遍历
有界阻塞队列:
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
queue.put("item"); // 阻塞插入
String item = queue.take(); // 阻塞取出
可选有界/无界:
// 无界队列
BlockingQueue<String> unbounded = new LinkedBlockingQueue<>();
// 有界队列
BlockingQueue<String> bounded = new LinkedBlockingQueue<>(100);
带优先级的无界队列:
BlockingQueue<Task> queue = new PriorityBlockingQueue<>(11, Comparator.comparing(Task::getPriority));
延迟队列:
class DelayItem implements Delayed {
// 必须实现getDelay()和compareTo()
}
DelayQueue<DelayItem> delayQueue = new DelayQueue<>();
跳表实现的并发有序Map:
ConcurrentSkipListMap<Integer, String> map = new ConcurrentSkipListMap<>();
map.put(3, "three");
map.put(1, "one");
// 保证遍历顺序是1->3
容器 | 特点 | 适用场景 |
---|---|---|
ConcurrentHashMap | 高并发K-V存储 | 缓存、共享数据存储 |
CopyOnWriteArrayList | 读多写少 | 监听器列表、配置数据 |
ConcurrentLinkedQueue | 无界非阻塞队列 | 任务队列、消息传递 |
ArrayBlockingQueue | 有界阻塞队列 | 生产者-消费者模式 |
LinkedBlockingQueue | 可选有界队列 | 线程池工作队列 |
ConcurrentSkipListMap | 有序并发Map | 需要排序的并发数据 |
合理选择容器类型:
避免热点竞争:
// 不好的做法 - 所有修改竞争同一键
map.compute("counter", (k, v) -> v + 1);
// 更好的做法 - 分散热点
map.compute(Thread.currentThread().getName(), (k, v) -> v + 1);
// 使用批量操作方法
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.putAll(otherMap);
// 而不是循环put
for(Map.Entry<String, Integer> entry : otherMap.entrySet()) {
map.put(entry.getKey(), entry.getValue()); // 多次获取锁
}
问题代码:
if(!map.containsKey(key)) {
map.put(key, value); // 非原子操作
}
解决方案:
map.putIfAbsent(key, value);
// 或者使用compute
map.compute(key, (k, v) -> v == null ? value : v);
迭代时可能不反映最新修改:
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// ...添加元素...
// 迭代期间可能有修改
for(String key : map.keySet()) {
// 可能看到部分修改
}
解决方案:
// 如果需要强一致性,需要额外同步
synchronized(map) {
for(String key : map.keySet()) {
// ...
}
}
确保修改对其他线程可见:
// 不安全的发布
class UnsafeHolder {
public static ConcurrentHashMap unsafeMap;
}
// 正确做法
class SafeHolder {
private static final ConcurrentHashMap safeMap = new ConcurrentHashMap();
public static ConcurrentHashMap getMap() {
return safeMap;
}
}
Java 8引入的并行操作方法:
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 并行forEach
map.forEach(2, (k, v) -> System.out.println(k + ":" + v));
// 并行reduce
int sum = map.reduceValues(2, Integer::sum);
// 并行search
String key = map.search(2, (k, v) -> v > 100 ? k : null);
实现生产者-消费者模式:
class CustomBlockingQueue<T> {
private final Queue<T> queue = new LinkedList<>();
private final int limit;
public CustomBlockingQueue(int limit) {
this.limit = limit;
}
public synchronized void put(T item) throws InterruptedException {
while(queue.size() == limit) {
wait();
}
queue.add(item);
notifyAll();
}
public synchronized T take() throws InterruptedException {
while(queue.isEmpty()) {
wait();
}
T item = queue.remove();
notifyAll();
return item;
}
}
public class InventorySystem {
private final ConcurrentHashMap<String, AtomicInteger> inventory;
public InventorySystem() {
inventory = new ConcurrentHashMap<>();
}
// 线程安全的库存扣减
public boolean deduct(String productId, int quantity) {
return inventory.computeIfPresent(productId, (k, v) -> {
int remaining = v.get() - quantity;
return remaining >= 0 ? new AtomicInteger(remaining) : v;
}) != null;
}
// 批量查询
public Map<String, Integer> getInventoryStatus(Set<String> productIds) {
return productIds.stream()
.collect(Collectors.toMap(
id -> id,
id -> inventory.getOrDefault(id, new AtomicInteger(0)).get()
));
}
}
通过合理使用J.U.C并发容器,可以构建出高性能、线程安全的并发系统。开发者应当根据具体场景选择合适的容器,并充分理解其特性才能发挥最大效益。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。