题目描述

链接: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();
    }
}