题目描述
链接:https://leetcode-cn.com/problems/building-h2o
现在有两种线程,氧 oxygen 和氢 hydrogen,你的目标是组织这两种线程来产生水分子。
存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。
氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。
示例 1:
输入: "HOH"
输出: "HHO"
解释: "HOH" 和 "OHH" 依然都是有效解。
思路
- 串行化,用一个volatile修饰变量,然后加锁
- 考虑CyclicBarrier+Semaphore,用三个线程,2个线程生产H,1个线程生产O,通过屏障拦截线程,一同向前走。
- 当然最好的方式当然是两个线程,生产2倍的H,1倍的O,然后组合起来,就像工厂生产线那样,但是不太适合做题。编程来源生活,可以发现多线程编程可以从工业生产和生活中获得灵感。
CyclicBarrier+Semaphore
import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.Semaphore; public class Test3 { // 信号量 Semaphore H; Semaphore O; // 障栅 CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() { @Override public void run(){ H.release(2); O.release(); } }); public Test3(){ H = new Semaphore(2); O = new Semaphore(1); } // 生产 H public void h() throws InterruptedException{ H.acquire(); System.out.print("H "); try { cyclicBarrier.await(); } catch (BrokenBarrierException brokenBarrierException) { System.out.println("error"); } } // 生产 O public void o() throws InterruptedException{ O.acquire(); System.out.print("O "); try { cyclicBarrier.await(); } catch (BrokenBarrierException brokenBarrierException) { System.out.println("error"); } } // main函数,开启三个线程,main线程等待三个线程完成任务,这里只生产10个H2O public static void main(String[] args) throws InterruptedException{ Test3 test3 = new Test3(); Thread thread1 = new Thread(() -> { try { int n = 10; while (n > 0) { n--; test3.h(); } } catch (InterruptedException e) { e.printStackTrace(); } }); Thread thread2 = new Thread(() -> { try { int n = 10; while (n > 0) { n--; test3.h(); } } catch (InterruptedException e) { e.printStackTrace(); } try { int n = 10; while (n > 0) { n--; test3.o(); } }); Thread thread3 = new Thread(() -> { try { int n = 10; while (n > 0) { n--; test3.o(); } } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); thread2.start(); thread3.start(); thread1.join(); thread2.join(); thread3.join(); } }