,敢教日月换新天。为有牺牲多壮志

[Java]LeetCode1117. H2O 生成 | Building H2O

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

There are two kinds of threads, oxygen and hydrogen. Your goal is to group these threads to form water molecules. There is a barrier where each thread has to wait until a complete molecule can be formed. Hydrogen and oxygen threads will be given a releaseHydrogen and releaseOxygen method respectfully, which will allow them to pass the barrier. These threads should pass the barrier in groups of three, and they must be able to immediately bond with each other to form a water molecule. You must guarantee that all the threads from one molecule bond before any other threads from the next molecule do.

In other words:

If an oxygen thread arrives at the barrier when no hydrogen threads are present, it has to wait for two hydrogen threads.
If a hydrogen thread arrives at the barrier when no other threads are present, it has to wait for an oxygen thread and another hydrogen thread.
Write synchronization code for oxygen and hydrogen molecules that enforces these constraints.

 

Example 1:

Input: "HOH"
Output: "HHO"
Explanation: "HOH" and "OHH" are also valid answers.
Example 2:

Input: "OOHHHH"
Output: "HHOHHO"
Explanation: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" and "OHHOHH" are also valid answers.
 

Constraints:

Total length of input string will be 3n, where 1 ≤ n ≤ 50.
Total number of H will be 2n in the input string.
Total number of O will be n in the input string.


现在有两种线程,氢 oxygen 和氧 hydrogen,你的目标是组织这两种线程来产生水分子。

存在一个屏障(barrier)使得每个线程必须等候直到一个完整水分子能够被产生出来。

氢和氧线程会被分别给予 releaseHydrogen 和 releaseOxygen 方法来允许它们突破屏障。

这些线程应该三三成组突破屏障并能立即组合产生一个水分子。

你必须保证产生一个水分子所需线程的结合必须发生在下一个水分子产生之前。

换句话说:

如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。
书写满足这些限制条件的氢、氧线程同步代码。

 

示例 1:

输入: "HOH"
输出: "HHO"
解释: "HOH" 和 "OHH" 依然都是有效解。
示例 2:

输入: "OOHHHH"
输出: "HHOHHO"
解释: "HOHHHO", "OHHHHO", "HHOHOH", "HOHHOH", "OHHHOH", "HHOOHH", "HOHOHH" 和 "OHHOHH" 依然都是有效解。
 

限制条件:

输入字符串的总长将会是 3n, 1 ≤ n ≤ 50;
输入字符串中的 “H” 总数将会是 2n;
输入字符串中的 “O” 总数将会是 n。


22ms

复制代码
 1 import java.util.concurrent.Semaphore;
 2 
 3 class H2O {
 4 
 5   private Semaphore s1,s2,s3,s4;
 6     
 7     public H2O() {
 8         s1 = new Semaphore(2); // H线程信号量
 9         s2 = new Semaphore(1); // O线程信号量
10         
11         s3 = new Semaphore(0); // 反应条件信号量
12         s4 = new Semaphore(0); // 反应条件信号量
13     }
14 
15     public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
16         s1.acquire(); // 保证只有2个H线程进入执行
17         s3.release(); // 释放H原子到达信号
18         s4.acquire(); // 等待O原子到达
19         releaseHydrogen.run();
20         s1.release(); // 相当于唤醒1个H线程
21     }
22 
23     public void oxygen(Runnable releaseOxygen) throws InterruptedException {
24         s2.acquire(); // 保证只有1个O线程进入执行
25         s4.release(2); // 释放O原子到达信号,因为有2个H线程等待所以释放2个
26         s3.acquire(2); // 等待H原子到达,2个原因同上
27         releaseOxygen.run();
28         s2.release(); // 相当于唤醒1个O线程
29     }
30 }
复制代码

23ms

复制代码
 1 import java.util.concurrent.CountDownLatch;
 2 import java.util.concurrent.Semaphore;
 3 
 4 class H2O {
 5     
 6     private Semaphore semaph1,semaph2,semaph3,semaph4;
 7 
 8     public H2O() {
 9         //用于保证输出两个H和一个O
10         semaph1 = new Semaphore(2); // H线程信号量
11         semaph2 = new Semaphore(1);  // O线程信号量
12         
13         //用于确认一次完整的打印是否已经完成
14         semaph3 = new Semaphore(0);
15         semaph4 = new Semaphore(0);
16     }
17 
18     public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
19         semaph1.acquire();  //等待H原子释放
20         semaph3.release();  // H原子释放完毕信号
21         semaph4.acquire();  // 等待O原子释放H信号
22         // releaseHydrogen.run() outputs "H". Do not change or remove this line.
23         releaseHydrogen.run();
24         semaph1.release();
25         //semaph3.release();
26         
27     }
28 
29     public void oxygen(Runnable releaseOxygen) throws InterruptedException {
30         semaph2.acquire();
31         semaph3.acquire(2); //等待H原子释放完毕信号
32         semaph4.release(2); //释放两个H原子
33         // releaseOxygen.run() outputs "O". Do not change or remove this line.
34         releaseOxygen.run();
35         semaph2.release();
36     }
37 }
复制代码

25ms

复制代码
 1 import java.util.concurrent.locks.Condition;
 2 import java.util.concurrent.locks.ReentrantLock;    
 3 class H2O {
 4         private volatile boolean flag = true;//true表示打印H
 5         private ReentrantLock lock = new ReentrantLock();
 6         private Condition hcondition = lock.newCondition();
 7         private Condition ocondition = lock.newCondition();
 8         private int i = 0;
 9 
10         public H2O() {
11 
12         }
13 
14         public void hydrogen(Runnable releaseHydrogen) throws InterruptedException{
15             try {
16                 lock.lock();
17                 while (!flag) {
18                     hcondition.await();
19                 }
20                 // releaseHydrogen.run() outputs "H". Do not change or remove this line.
21                 releaseHydrogen.run();
22                 i++;
23                 if (i % 2 == 0) {
24                     flag = false;
25                     ocondition.signalAll();
26                 }
27             } finally {
28                 lock.unlock();
29             }
30 
31 
32         }
33 
34         public void oxygen(Runnable releaseOxygen) throws InterruptedException {
35             try {
36                 lock.lock();
37                 while (flag) {
38                     ocondition.await();
39                 }
40                 // releaseOxygen.run() outputs "H". Do not change or remove this line.
41                 releaseOxygen.run();
42                 flag = true;
43                 hcondition.signalAll();
44             } finally {
45                 lock.unlock();
46             }
47         }
48     }
复制代码

 

posted @   为敢技术  阅读(828)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示
哥伦布
09:09发布
哥伦布
09:09发布
3°
多云
东南风
3级
空气质量
相对湿度
47%
今天
中雨
3°/15°
周三
中雨
3°/13°
周四
小雪
-1°/6°