惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Latest
Security Latest
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
N
Netflix TechBlog - Medium
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
C
Cyber Attacks, Cyber Crime and Cyber Security
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Threat Research - Cisco Blogs
NISL@THU
NISL@THU
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
J
Java Code Geeks
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
MyScale Blog
MyScale Blog
T
Tor Project blog
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
P
Privacy & Cybersecurity Law Blog
MongoDB | Blog
MongoDB | Blog
Simon Willison's Weblog
Simon Willison's Weblog
C
Cybersecurity and Infrastructure Security Agency CISA
L
LINUX DO - 热门话题
小众软件
小众软件
G
GRAHAM CLULEY
P
Privacy International News Feed
AWS News Blog
AWS News Blog
Know Your Adversary
Know Your Adversary
P
Palo Alto Networks Blog
人人都是产品经理
人人都是产品经理
S
Schneier on Security
Scott Helme
Scott Helme
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog RSS Feed
T
The Exploit Database - CXSecurity.com
Recent Announcements
Recent Announcements
E
Exploit-DB.com RSS Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
U
Unit 42
The Register - Security
The Register - Security
S
Securelist
Martin Fowler
Martin Fowler
Project Zero
Project Zero
大猫的无限游戏
大猫的无限游戏
Cisco Talos Blog
Cisco Talos Blog

博客园 - 小纸条

ruoyiai 启动指南 反向传播 numpy的使用 B 和 B+树 红黑树 ruoyi-vue 梯度下降法 博弈论 离散化 AcWing 907. 区间覆盖 AcWing 906. 区间分组 AcWing 908 最大不相交区间数量 AcWing 905. 区间选点 AcWing 104. 货仓选址 动态规划经典题 窗口函数 1226. 哲学家进餐 1195. 交替打印字符串 1116. 打印零与奇偶数 关联子查询
1117. H2O 生成
小纸条 · 2025-10-28 · via 博客园 - 小纸条

1117. H2O 生成

题目描述

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

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

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

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

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

换句话说:

  • 如果一个氧线程到达屏障时没有氢线程到达,它必须等候直到两个氢线程到达。
  • 如果一个氢线程到达屏障时没有其它线程到达,它必须等候直到一个氧线程和另一个氢线程到达。

书写满足这些限制条件的氢、氧线程同步代码。

示例 1:

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

示例 2:

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

提示:

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

解法

Java

class H2O {
    private int hydrogenCount = 0;
    private int oxygenCount = 0;

    public H2O() {
        
    }

    public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
        synchronized (this) {
            // 等待直到可以组成一个水分子(需要少于2个H)
            while (hydrogenCount == 2) {
                wait();
            }
            
            // 释放氢线程
            releaseHydrogen.run();
            hydrogenCount++;
            
            // 检查是否已经组成一个完整的水分子(2个H + 1个O)
            if (hydrogenCount == 2 && oxygenCount == 1) {
                hydrogenCount = 0;
                oxygenCount = 0;
            }
            
            notifyAll();
        }
    }

    public void oxygen(Runnable releaseOxygen) throws InterruptedException {
        synchronized (this) {
            // 等待直到可以组成一个水分子(需要少于1个O)
            while (oxygenCount == 1) {
                wait();
            }
            
            // 释放氧线程
            releaseOxygen.run();
            oxygenCount++;
            
            // 检查是否已经组成一个完整的水分子(2个H + 1个O)
            if (hydrogenCount == 2 && oxygenCount == 1) {
                hydrogenCount = 0;
                oxygenCount = 0;
            }
            
            notifyAll();
        }
    }
}

Java

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class H2O {
    private Lock lock = new ReentrantLock();
    private Condition hydrogenCondition = lock.newCondition();
    private Condition oxygenCondition = lock.newCondition();
    
    private volatile int hydrogenCount = 0;
    private volatile int oxygenCount = 0;

    public H2O() {
        
    }

    public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
        lock.lock();
        try {
            // 等待直到可以添加氢原子(最多2个)
            while (hydrogenCount == 2) {
                hydrogenCondition.await();
            }
            
            // 释放氢原子
            releaseHydrogen.run();
            hydrogenCount++;
            
            // 检查是否形成完整水分子
            checkAndReset();
        } finally {
            lock.unlock();
        }
    }

    public void oxygen(Runnable releaseOxygen) throws InterruptedException {
        lock.lock();
        try {
            // 等待直到可以添加氧原子(最多1个)
            while (oxygenCount == 1) {
                oxygenCondition.await();
            }
            
            // 释放氧原子
            releaseOxygen.run();
            oxygenCount++;
            
            // 检查是否形成完整水分子
            checkAndReset();
        } finally {
            lock.unlock();
        }
    }
    
    private void checkAndReset() {
        // 如果形成了完整水分子(2个H + 1个O)
        if (hydrogenCount == 2 && oxygenCount == 1) {
            hydrogenCount = 0;
            oxygenCount = 0;
            // 唤醒所有等待的线程
            hydrogenCondition.signalAll();
            oxygenCondition.signalAll();
        }
    }
}

...