网站首页 > java教程 正文
JUC - 辅助类
JUC(java.util.concurrent)是在Java 5中引入的一个并发编程的扩展库,目的是为了更加方便、快捷和安全地实现并发编程。它提供了一系列的工具类、锁、队列以及原子类等来协调多线程之间的操作。
基于现代硬件不断地发展,为了充分利用服务器资源,并发编程在我们的开发中已经无处不在,今天主要了解下JUC包中提供的几个工具类,让我们在并发编程时提供助力。
简介
Java并发编程是一门复杂的技术,其中有一些难点需要特别注意。以下是一些Java并发编程的难点:
- 线程安全:多线程执行的代码必须是线程安全的,否则会产生竞态条件和其他问题。
- 死锁:当多个线程因为互相等待其他线程释放锁而无法继续执行时,就会产生死锁。
- 竞态条件:当多个线程试图同时访问同一个共享资源时,就会产生竞态条件。
- 内存可见性:多个线程同时访问同一个变量时,可能会产生内存可见性问题,即一个线程对变量的修改不会立即被其他线程所感知。
- 并发集合类:Java提供了一些并发集合类,如ConcurrentHashMap和ConcurrentLinkedQueue,但使用它们需要注意一些细节问题。
- 线程池:线程池是Java并发编程中的一个重要概念,但线程池的使用也需要注意一些问题,如线程池大小、任务队列类型等。
- CAS操作:Java提供了CAS(Compare-And-Swap)操作,可以用于实现非阻塞算法,但使用CAS操作需要非常小心,以免产生ABA问题等。
工具类
- CountDownLatch
CountDownLatch是一个同步辅助类,使用一个给定数量的计数器,当该计数器不为0时,将程序阻塞在wait()处,当线程执行完成后通过调用countDown()使计数器减一, 直到计数器为0后才会继续执行后续代码。 主要实现某个任务依赖其他一个或多个异步任务的执行结果的场景
核心方法:
/**
* 定义计数器数量,用于定义多少个执行线程
*/
public CountDownLatch(int count);
/**
* 阻塞方法,直到计数器为0时才会继续执行后续代码
*/
public void await();
/**
* 每次调用改方法,则计数器减一
*/
public void countDown();
- CyclicBarrier
CyclicBarrier内部同样定义了计数器,只不过每当有线程执行完后改计数器加一,直至达到定义数量后,执行定义的回调函数与await()后续代码。 与CountDownLatch相比,CyclicBarrier会对子任务阻塞,而CountDownLatch则阻塞主任务;另外CyclicBarrier可以重复使用。 主要实现某个回调函数在一个或多个线程执行完成后触发的情形
核心方法:
/**
* 定义计数器数量与回调函数
*/
public CyclicBarrier(int parties, Runnable barrierAction);
/**
* 阻塞方法,当有线程执行到则计数器加一,等到达到目标数后才会继续后续代码
*/
public int await();
/**
* 通过该方法可以实现计数器的重置
*/
public void reset();
- Semaphore
信号量通常用于限制可以访问某些(物理或逻辑)资源的线程数。 适用于有限资源数量的控制
核心方法:
/**
* 定义许可数量
*/
public Semaphore(int permits);
/**
* 申请许可,改方法会阻塞程序
*/
public void acquire();
/**
* 释放许可
*/
public void release();
示例
CountDownLatch的使用场景
CountDownLatch是Java并发包中的一个工具类,它可以实现线程之间的协作。具体来说,CountDownLatch可以让一个线程等待多个线程执行完毕,再继续执行。CountDownLatch常用于以下场景:
- 主线程等待多个子线程执行完毕。
- 多个子线程等待某个共同任务的完成。
- 模拟并发请求,等待所有请求都响应完毕再进行下一步操作。
- 统计多个线程执行的时间。
@Test
public void test() throws InterruptedException {
int count = 10;
CountDownLatch countDownLatch = new CountDownLatch(count);
IntStream.range(0,count).forEach(i->{
new Thread(()->{
System.out.println( "执行线程:"+ i );
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
countDownLatch.countDown();
}).start();
});
countDownLatch.await();
System.out.println("线程执行完成");
}
CyclicBarrier的使用场景
它允许多个线程在某个屏障处等待,直到所有线程都到达该屏障时才会继续执行。
CyclicBarrier 适用于一组线程需要相互等待,直到所有线程都完成某个任务后才能继续执行下一步操作的场景。例如,一个大型的计算任务可以被分成多个子任务, 每个子任务由一个线程执行。当所有子任务完成后,这些线程需要等待,直到所有子任务都完成,然后再执行下一步操作。
另外,CyclicBarrier 还可以用于优化代码性能。例如,当我们需要等待多个线程都完成某项工作后,才能进行下一步操作。此时,我们可以使用 CyclicBarrier 来实现等待, 而不是使用 Thread.sleep() 方法等待一段时间。这样可以避免无谓的等待时间,提高代码效率。
@Test
public void test() {
int count = 10;
AtomicBoolean finish = new AtomicBoolean(false);
CyclicBarrier cyclicBarrier = new CyclicBarrier(count, ()->{
System.out.println("线程执行完成");
finish.set(true);
});
IntStream.range(0,count).forEach(i->{
new Thread(()->{
System.out.println( "执行线程:"+ i );
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
}
}).start();
});
while (!finish.get()){}
}
Semaphore的使用场景
它可以控制同时访问某个共享资源的线程数量。常用于限制同时访问某个资源的线程数量,例如数据库连接池、线程池等。
- 控制并发线程数:Semaphore可以限制并发线程数,从而控制系统资源的使用情况。
- 控制访问资源数:Semaphore可以控制同时访问某个资源的线程数量,例如数据库连接池,限制连接数。
- 实现生产者-消费者模型:Semaphore可以与阻塞队列一起使用,实现生产者-消费者模型,控制生产者和消费者的数量。
- 多个线程间的协作:Semaphore可以用于多个线程之间的协作,例如某个线程需要等待某些条件满足后才能继续执行,可以使用Semaphore来实现等待和唤醒操作。
@Test
public void test() {
int count = 10;
Semaphore semaphore = new Semaphore(3);
IntStream.range(0,count).forEach(i->{
new Thread(()->{
try {
semaphore.acquire();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println( "执行线程:"+ i );
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
semaphore.release();
}).start();
});
while (true){}
}
结束语
涉及到线程的开发都伴随着复杂性,不管是在代码调试上还是理解线程切换与安全性上,JUC提供的各种强大的工具类将并发编程的复杂性进行了封装,不管是在使用或是扩展上,都能通过简单的几行代码实现多线程的各种协调工作。
猜你喜欢
- 2025-07-19 Java AtomicInteger操作详解(java attachment)
- 2025-07-19 无锁同步-JAVA之Volatile、Atomic和CAS
- 2025-07-19 Java 作用域详解:从变量可见性到代码封装
- 2025-07-19 CompletableFuture源码分析(fragment源码分析)
- 2025-07-19 Java并发编程从入门到进阶 多场景实战
- 2025-07-19 一文搞懂 CAS 操作与 ABA 问题:高并发编程的关键知识点
- 2025-07-19 Java 内存模型、JVM 内存结构(java的内存模型)
- 2025-07-19 Java面试必备八股文(java面试必备八股文河北人社)
- 2025-07-19 Java面试都在问的CAS,你还没掌握吗?
- 2025-07-19 java VarHandle介绍(java variant)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)