目录
juc包下的常用工具类
1. 信号量——Semaphore
2. 计数器——CountDownLatch3. 循环栅栏——CyclicBarrier
4. 两个线程之间的交换器——Exchanger
信号量——Semaphore
信号量Semaphore 就是一个计数器,表示当前可用资源的个数。
关于信号量Semaphore有两个核心操作
P-申请资源操作
V-释放资源操作Semaphore的PV加减操作都是原子性的,在多线程场景下可以直接使用
import java.util.concurrent.Semaphore; /** * 信号量的使用 无参 */ public class SemaphoreTest { public static void main(String[] args) { // 在构造参数传入可用资源的个数 // 可用资源为5 Semaphore semaphore = new Semaphore(5); Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + "准备申请资源"); // P操作,每次申请1个资源 // 当前若可用资源为0,调用acquire的线程就会阻塞,直到占有线程释放资源 semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "获取资源成功"); Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "释放资源"); // V操作,每次释放1个资源 semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } }; for (int i = 0; i < 10; i++) { Thread t = new Thread(runnable, String.valueOf(i + 1)); t.start(); } } }
当前可用资源数为5,此时只有5个线程获取资源成功。其他线程都会阻塞在acquire方法处,
等待占有线程释放资源。
import java.util.concurrent.Semaphore; /** * 信号量的使用 有参 **/ public class SemaphoreTest2 { public static void main(String[] args) { // 在构造参数传入可用资源的个数 // 可用资源为6个 Semaphore semaphore = new Semaphore(6); Runnable runnable = new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + "准备申请资源"); // P操作,每次申请两个资源 semaphore.acquire(2); System.out.println(Thread.currentThread().getName() + "获取资源成功"); Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "释放资源"); // V操作,默认释放2个占有的资源 semaphore.release(2); }catch (InterruptedException e) { e.printStackTrace(); } } }; for (int i = 0; i < 10; i++) { Thread t = new Thread(runnable,String.valueOf(i + 1)); t.start(); } } }
计数器——CountDownLatch
CountDownLatch -大号的join方法
调用await方法的线程,需要等待其他线程将计数器减为0,才能继续恢复执行。import java.util.Random; import java.util.concurrent.CountDownLatch; /** * 使用CountDownLatch.await方法的线程会阻塞,直到所有等待线程全部执行结束为止 * 大号进阶版本的join方法 */ public class CountDownLatchTest { public static void main(String[] args) throws InterruptedException { // 等待线程需要等待的线程数,必须等这10个子线程全部执行完毕再恢复执行 CountDownLatch latch = new CountDownLatch(10); Runnable runnable = new Runnable() { @Override public void run() { try { Thread.sleep(new Random().nextInt(1000)); System.out.println(Thread.currentThread().getName() + "到达终点"); // 计数器 - 1 latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }; for (int i = 0; i < 10; i++) { Thread t = new Thread(runnable, "运动员" + i); t.start(); } // main线程就是裁判线程,需要等待所有运动员到终点再恢复执行 // 直到所有线程调用countdown方法将计数器减为0继续执行 latch.await(); System.out.println("比赛结束"); } }