温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java中并发容器J.U.C怎么用

发布时间:2021-10-19 15:52:31 来源:亿速云 阅读:166 作者:柒染 栏目:大数据
# 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"); 

特性

  • 分段锁技术(Java 7)或CAS+synchronized(Java 8+)
  • 高并发下性能远优于Hashtable
  • 不允许null键/值

高级API

// 原子更新 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)); 

2. CopyOnWriteArrayList

适用场景

读多写少的并发场景,如事件监听器列表

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("item1"); // 写时复制 String item = list.get(0); // 无锁读取 

注意事项

  • 写操作性能较差(需要数组拷贝)
  • 迭代器反映的是创建时的快照

3. ConcurrentLinkedQueue

无界非阻塞队列实现:

ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>(); queue.offer("element1"); String head = queue.poll(); 

特点: - CAS实现的无锁算法 - 高性能但size()方法需要遍历

4. BlockingQueue家族

ArrayBlockingQueue

有界阻塞队列:

BlockingQueue<String> queue = new ArrayBlockingQueue<>(10); queue.put("item"); // 阻塞插入 String item = queue.take(); // 阻塞取出 

LinkedBlockingQueue

可选有界/无界:

// 无界队列 BlockingQueue<String> unbounded = new LinkedBlockingQueue<>(); // 有界队列 BlockingQueue<String> bounded = new LinkedBlockingQueue<>(100); 

PriorityBlockingQueue

带优先级的无界队列:

BlockingQueue<Task> queue = new PriorityBlockingQueue<>(11, Comparator.comparing(Task::getPriority)); 

DelayQueue

延迟队列:

class DelayItem implements Delayed { // 必须实现getDelay()和compareTo() } DelayQueue<DelayItem> delayQueue = new DelayQueue<>(); 

5. ConcurrentSkipListMap

跳表实现的并发有序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 需要排序的并发数据

四、性能优化技巧

  1. 合理选择容器类型

    • 读远大于写:CopyOnWrite系列
    • 严格吞吐量要求:ConcurrentHashMap
    • 顺序访问需求:ConcurrentSkipListMap
  2. 避免热点竞争

// 不好的做法 - 所有修改竞争同一键 map.compute("counter", (k, v) -> v + 1); // 更好的做法 - 分散热点 map.compute(Thread.currentThread().getName(), (k, v) -> v + 1); 
  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()); // 多次获取锁 } 

五、常见问题解决方案

1. 复合操作问题

问题代码:

if(!map.containsKey(key)) { map.put(key, value); // 非原子操作 } 

解决方案:

map.putIfAbsent(key, value); // 或者使用compute map.compute(key, (k, v) -> v == null ? value : v); 

2. 弱一致性问题

迭代时可能不反映最新修改:

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>(); // ...添加元素... // 迭代期间可能有修改 for(String key : map.keySet()) { // 可能看到部分修改 } 

解决方案:

// 如果需要强一致性,需要额外同步 synchronized(map) { for(String key : map.keySet()) { // ... } } 

3. 内存一致性问题

确保修改对其他线程可见:

// 不安全的发布 class UnsafeHolder { public static ConcurrentHashMap unsafeMap; } // 正确做法 class SafeHolder { private static final ConcurrentHashMap safeMap = new ConcurrentHashMap(); public static ConcurrentHashMap getMap() { return safeMap; } } 

六、高级特性应用

1. ConcurrentHashMap的并行操作

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); 

2. 自定义BlockingQueue

实现生产者-消费者模式:

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; } } 

七、最佳实践总结

  1. 优先使用J.U.C而非同步容器:如用ConcurrentHashMap代替Collections.synchronizedMap
  2. 了解各容器的实现原理:如ConcurrentHashMap的分段锁机制
  3. 避免不必要的同步:利用并发容器的原子方法
  4. 注意迭代器的弱一致性:不要在迭代过程中做结构性修改
  5. 合理配置容量:特别是BlockingQueue实现类
  6. 利用Java 8+的新API:如ConcurrentHashMap的流式操作

八、实战案例:电商库存系统

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并发容器,可以构建出高性能、线程安全的并发系统。开发者应当根据具体场景选择合适的容器,并充分理解其特性才能发挥最大效益。 “`

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI