1114. 按序打印
class Foo {// 定义两个 CountDownLatch 对象,分别用于控制两次的顺序private final CountDownLatch firstDone;private final CountDownLatch secondDone;// 构造函数public Foo() {firstDone = new CountDownLatch(1); // 用于等待 first 方法完成secondDone = new CountDownLatch(1); // 用于等待 second 方法完成}// 第一个方法public void first(Runnable printFirst) throws InterruptedException {printFirst.run(); // 输出 "first"firstDone.countDown(); // 调用完成后,减少计数器,通知等待的线程}// 第二个方法public void second(Runnable printSecond) throws InterruptedException {firstDone.await(); // 等待 firstDone 的计数器变为 0,即等待 first 方法完成printSecond.run(); // 输出 "second"secondDone.countDown(); // 完成后,减少计数器,通知等待的线程}// 第三个方法public void third(Runnable printThird) throws InterruptedException {secondDone.await(); // 等待 secondDone 的计数器变为 0,即等待 second 方法完成printThird.run(); // 输出 "third"}}
1115. 交替打印 FooBar
class FooBar {private int n; // 要打印的次数private final Semaphore fooSemaphore = new Semaphore(1); // foo 方法的信号量,初始为 1,表示可以先执行 fooprivate final Semaphore barSemaphore = new Semaphore(0); // bar 方法的信号量,初始为 0,表示初始情况下 bar 不可执行// 构造函数,初始化打印次数public FooBar(int n) {this.n = n; // 设置要打印的次数}// foo 方法public void foo(Runnable printFoo) throws InterruptedException {for (int i = 0; i < n; i++) {fooSemaphore.acquire(); // 获取 foo 的许可,如果没有许可则阻塞printFoo.run(); // 调用传入的 Runnable,打印 "foo"barSemaphore.release(); // 打印完成后,释放 bar 的许可,允许 bar 方法执行}}// bar 方法public void bar(Runnable printBar) throws InterruptedException {for (int i = 0; i < n; i++) {barSemaphore.acquire(); // 获取 bar 的许可,如果没有许可则阻塞printBar.run(); // 调用传入的 Runnable,打印 "bar"fooSemaphore.release(); // 打印完成后,释放 foo 的许可,允许 foo 方法执行}}
}
1116. 打印零与奇偶数
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.function.IntConsumer;class ZeroEvenOdd {private final int n; // 要打印的最大数字private final CyclicBarrier[] cbs = new CyclicBarrier[3]; // 用于控制线程同步的屏障// 构造函数,初始化 n 和 CyclicBarrierpublic ZeroEvenOdd(int n) {this.n = n;// 初始化每个屏障,等待两个线程for (int i = 0; i < cbs.length; i++) {cbs[i] = new CyclicBarrier(2);}}// 打印0的方法public void zero(IntConsumer printNumber) throws InterruptedException {for (int i = 1; i <= n; i++) {printNumber.accept(0); // 打印 0try {// 根据当前 i 的奇偶性决定等待 odd 还是 evenif (i % 2 == 1) {cbs[1].await(); // 等待 odd 打印} else {cbs[2].await(); // 等待 even 打印}cbs[0].await(); // 等待下一轮的 0} catch (BrokenBarrierException e) {e.printStackTrace(); // 捕获并打印异常堆栈}}}// 打印偶数的方法public void even(IntConsumer printNumber) throws InterruptedException {for (int i = 2; i <= n; i += 2) {try {cbs[2].await(); // 等待 zero 打印 0printNumber.accept(i); // 打印当前偶数cbs[0].await(); // 等待下一轮的 0} catch (BrokenBarrierException e) {e.printStackTrace(); // 捕获并打印异常堆栈}}}// 打印奇数的方法public void odd(IntConsumer printNumber) throws InterruptedException {for (int i = 1; i <= n; i += 2) {try {cbs[1].await(); // 等待 zero 打印 0printNumber.accept(i); // 打印当前奇数cbs[0].await(); // 等待下一轮的 0} catch (BrokenBarrierException e) {e.printStackTrace(); // 捕获并打印异常堆栈}}}
}
1117. H2O 生成
class H2O {// 表示当前状态,0 代表可以产生氧气,1 和 2 代表产生了一个和两个氢原子的状态private volatile int state = 0;// 用于线程同步的对象private Object obj = new Object();public H2O() {}// 产生氢原子的方法public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {// 对同步对象加锁synchronized (obj) {// 当状态为 2 时,说明已经有两个氢原子,需要等待氧气产生后才能继续产生氢原子while (state == 2) {obj.wait();}// 状态加一,表示产生了一个氢原子state++;// 执行产生氢原子的操作releaseHydrogen.run();// 通知其他等待的线程obj.notifyAll();}}// 产生氧气的方法public void oxygen(Runnable releaseOxygen) throws InterruptedException {// 对同步对象加锁synchronized (obj) {// 当状态不是 2 时,说明氢原子数量不足,需要等待氢原子产生到两个后才能产生氧气while (state!= 2) {obj.wait();}// 将状态重置为 0,表示可以继续产生氢原子和氧气的新循环state = 0;// 执行产生氧气的操作releaseOxygen.run();// 通知其他等待的线程obj.notifyAll();}}}
1195. 交替打印字符串
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.IntConsumer;class FizzBuzz {private final int n; // 最大数字private final ReentrantLock lock = new ReentrantLock(); // 用于控制线程间的访问private int state = 0; // 状态变量,用于控制输出private final Condition condition = lock.newCondition(); // 条件变量,用于线程之间的通知// 构造函数,初始化最大数字 npublic FizzBuzz(int n) {this.n = n;}// printFizz.run() 输出 "fizz"public void fizz(Runnable printFizz) throws InterruptedException {for (int i = 3; i <= n; i += 3) {lock.lock(); // 获取锁try {// 跳过能被 15 整除的数字,因为它会被 fizzbuzz 方法处理if (i % 3 == 0 && i % 5 == 0) continue;// 等待状态变为 3,表示需要打印 "fizz"while (state != 3) {condition.await();}printFizz.run(); // 打印 "fizz"state = 0; // 重置状态condition.signalAll(); // 通知其他等待的线程} finally {lock.unlock(); // 解锁}}}// printBuzz.run() 输出 "buzz"public void buzz(Runnable printBuzz) throws InterruptedException {for (int i = 5; i <= n; i += 5) {lock.lock(); // 获取锁try {// 跳过能被 15 整除的数字,因为它会被 fizzbuzz 方法处理if (i % 3 == 0 && i % 5 == 0) continue;// 等待状态变为 5,表示需要打印 "buzz"while (state != 5) {condition.await();}printBuzz.run(); // 打印 "buzz"state = 0; // 重置状态condition.signalAll(); // 通知其他等待的线程} finally {lock.unlock(); // 解锁}}}// printFizzBuzz.run() 输出 "fizzbuzz"public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {for (int i = 15; i <= n; i += 15) {lock.lock(); // 获取锁try {// 等待状态变为 15,表示需要打印 "fizzbuzz"while (state != 15) {condition.await();}printFizzBuzz.run(); // 打印 "fizzbuzz"state = 0; // 重置状态condition.signalAll(); // 通知其他等待的线程} finally {lock.unlock(); // 解锁}}}// printNumber.accept(x) 输出 "x",其中 x 是一个整数public void number(IntConsumer printNumber) throws InterruptedException {for (int i = 1; i <= n; i++) {try {lock.lock(); // 获取锁// 等待状态为 0,表示可以打印数字while (state != 0) {condition.await();}// 检查 i 是否是 FizzBuzz 的情况if (i % 3 != 0 && i % 5 != 0) {printNumber.accept(i); // 打印数字} else {// 根据数字的特性设置状态if (i % 3 == 0 && i % 5 == 0) state = 15; // 设置状态为方程的状态else if (i % 3 == 0) state = 3; // 设置状态为打印 "fizz"else if (i % 5 == 0) state = 5; // 设置状态为打印 "buzz"condition.signalAll(); // 通知其他等待的线程}} finally {lock.unlock(); // 解锁}}}
}
1226. 哲学家进餐