Java并发编程与高并发解决方案之并发容器(J.U.C).docx
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
### Java并发编程与高并发解决方案之并发容器(J.U.C) #### 并发容器J.U.C 在Java中,为了提供高性能、低延迟的并发数据结构,Java提供了多种并发容器类,这些类主要位于`java.util.concurrent`包内,通常被称为J.U.C(Java Util Concurrency)容器。 ##### 1. CopyOnWriteArrayList `CopyOnWriteArrayList`是一个线程安全的列表类,它在添加元素时采用写时复制的方式。当进行修改操作时,会创建当前数组的一个副本,并将新元素插入到副本中,然后再用副本替换原来的数组。这种方式可以避免在遍历时进行同步操作,从而提高读取操作的效率。但是,由于每次修改都需要复制整个数组,因此写入操作的开销较大。 **应用场景:** - 当读取操作远多于写入操作时,使用`CopyOnWriteArrayList`比较合适。 - 当需要一个线程安全的列表,但又不希望在遍历过程中锁定整个列表时。 ##### 2. CopyOnWriteArraySet `CopyOnWriteArraySet`是基于`CopyOnWriteArrayList`实现的线程安全的Set集合。它的内部使用了一个`CopyOnWriteArrayList`来存储元素。因此,它也具有与`CopyOnWriteArrayList`相同的特点:读操作不加锁,写操作会复制整个数组。 **应用场景:** - 当需要一个线程安全的Set集合,并且读操作远多于写操作时。 ##### 3. ConcurrentSkipListSet `ConcurrentSkipListSet`是一个非阻塞的线程安全的SortedSet实现。它使用跳表作为其底层数据结构,跳表是一种类似于链表的数据结构,但在每个节点上还额外维护了多个指向后续节点的指针,使得查找时间复杂度降低到O(log n)。这种实现方式使得`ConcurrentSkipListSet`在进行大量并发操作时仍然能保持较高的性能。 **应用场景:** - 需要排序功能,并且对性能有较高要求的场景。 ##### 4. ConcurrentHashMap `ConcurrentHashMap`是一个线程安全的哈希映射实现。它通过将数据分成多个段(segment),每个段有自己的锁,这样可以同时对不同的段进行操作而不会发生冲突,从而提高并发性能。在Java 8及以后版本中,`ConcurrentHashMap`进一步优化了设计,采用了一种更加灵活的分段锁机制,使得其性能更加优秀。 **应用场景:** - 需要一个线程安全的映射类型容器,并且对性能有较高要求。 ##### 5. ConcurrentSkipListMap `ConcurrentSkipListMap`是一个非阻塞的线程安全的SortedMap实现。与`ConcurrentSkipListSet`类似,它也使用跳表作为底层数据结构,能够提供高效的并发访问能力。 **应用场景:** - 需要排序功能,并且对性能有较高要求的场景。 #### AQS同步组件 AQS(AbstractQueuedSynchronizer)是一个用于构建锁和同步器的框架,它提供了一个队列来管理等待的线程。许多J.U.C中的同步工具都是基于AQS实现的。 ##### 1. CountDownLatch `CountDownLatch`是一个同步辅助类,允许一个或多个线程等待其他线程完成操作。它通过一个计数器来控制线程的等待和继续执行。当计数器的值减为零时,所有等待的线程被唤醒。 **示例代码**: ```java @Slf4j public class CountDownLatchExample1 { private final static int threadCount = 200; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final CountDownLatch countDownLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { test(threadNum); } catch (Exception e) { log.error("exception", e); } finally { countDownLatch.countDown(); } }); } //countDownLatch.await(); // 无限期等待 countDownLatch.await(10, TimeUnit.MILLISECONDS); // 等待10毫秒后不再等待 log.info("finish"); exec.shutdown(); // 此方法不会立即终止线程运行,而是要等已开启的线程全部执行完关闭 } private static void test(int threadNum) throws Exception { Thread.sleep(100); log.info("{}", threadNum); Thread.sleep(100); } } ``` **应用场景:** - 当需要等待一系列操作完成后才能继续执行某个任务时。 ##### 2. Semaphore `Semaphore`(信号量)用于控制能够访问某些资源(如固定数量的许可证)的线程数量。它能够限制并发操作的数量,对于限制系统资源的访问非常有用。 **示例代码**: ```java @Slf4j public class SemaphoreExample1 { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { semaphore.acquire(); // 获取一个许可 test(threadNum); semaphore.release(); // 释放一个许可 } catch (Exception e) { log.error("exception", e); } }); } exec.shutdown(); } private static void test(int threadNum) throws Exception { log.info("{}", threadNum); Thread.sleep(1000); } } ``` **应用场景:** - 当需要限制并发访问的数量时,比如控制并发访问数据库连接池的线程数量。 ##### 3. CyclicBarrier `CyclicBarrier`是一个让一组线程等待至某状态之后再全部同时执行的辅助类。它支持一个可选的“屏障动作”,该动作会在最后一个线程到达屏障时执行。 **示例代码**: ```java @Slf4j public class CyclicBarrierExample2 { private static CyclicBarrier barrier = new CyclicBarrier(5); public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int threadNum = i; Thread.sleep(1000); executor.execute(() -> { try { race(threadNum); } catch (Exception e) { log.error("exception", e); } }); } executor.shutdown(); } private static void race(int threadNum) throws Exception { // ... 这里省略了具体的实现细节 ... } } ``` **应用场景:** - 当多个线程需要等待彼此完成某些操作后再一起执行时,例如模拟比赛场景中的发令枪。
- 粉丝: 8926
- 资源: 19万+
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助