现在有两种线程,氢 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。

思路:说白了就是控制个顺序。互相pv一下。可以去找一下我写的操作系统多线程控制。

class H2O {private Semaphore h = new Semaphore(2);private Semaphore o = new Semaphore(0);public H2O() {}public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {h.acquire();// releaseHydrogen.run() outputs "H". Do not change or remove this line.releaseHydrogen.run();o.release();}public void oxygen(Runnable releaseOxygen) throws InterruptedException {o.acquire(2);// releaseOxygen.run() outputs "O". Do not change or remove this line.releaseOxygen.run();h.release(2);}
}

Semaphore简介

Semaphore,是JDK1.5的java.util.concurrent并发包中提供的一个并发工具类。

所谓Semaphore即 信号量 的意思。

这个叫法并不能很好地表示它的作用,更形象的说法应该是许可证管理器。

其作用在JDK注释中是这样描述的:

A counting semaphore.
Conceptually, a semaphore maintains a set of permits.
Each {@link #acquire} blocks if necessary until a permit is available, and then takes it.
Each {@link #release} adds a permit, potentially releasing a blocking acquirer.
However, no actual permit objects are used; the {@code Semaphore} just keeps a count of the number available and acts accordingly.

翻译过来,就是:

Semaphore是一个计数信号量。
从概念上将,Semaphore包含一组许可证。
如果有需要的话,每个acquire()方法都会阻塞,直到获取一个可用的许可证。
每个release()方法都会释放持有许可证的线程,并且归还Semaphore一个可用的许可证。
然而,实际上并没有真实的许可证对象供线程使用,Semaphore只是对可用的数量进行管理维护。
2.Semaphore方法说明
Semaphore的方法如下:

——Semaphore(permits)

初始化许可证数量的构造函数

——Semaphore(permits,fair)

初始化许可证数量和是否公平模式的构造函数

——isFair()

是否公平模式FIFO

——availablePermits()

获取当前可用的许可证数量

——acquire()

当前线程尝试去阻塞的获取1个许可证。

此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:

当前线程获取了1个可用的许可证,则会停止等待,继续执行。
当前线程被中断,则会抛出InterruptedException异常,并停止等待,继续执行。
——acquire(permits)

当前线程尝试去阻塞的获取permits个许可证。

此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:

当前线程获取了n个可用的许可证,则会停止等待,继续执行。
当前线程被中断,则会抛出InterruptedException异常,并停止等待,继续执行。
——acquierUninterruptibly()

当前线程尝试去阻塞的获取1个许可证(不可中断的)。

此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:

当前线程获取了1个可用的许可证,则会停止等待,继续执行。
——acquireUninterruptibly(permits)

当前线程尝试去阻塞的获取permits个许可证。

此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:

当前线程获取了n个可用的许可证,则会停止等待,继续执行。
——tryAcquire()

当前线程尝试去获取1个许可证。

此过程是非阻塞的,它只是在方法调用时进行一次尝试。

如果当前线程获取了1个可用的许可证,则会停止等待,继续执行,并返回true。

如果当前线程没有获得这个许可证,也会停止等待,继续执行,并返回false。

——tryAcquire(permits)

当前线程尝试去获取permits个许可证。

此过程是非阻塞的,它只是在方法调用时进行一次尝试。

如果当前线程获取了permits个可用的许可证,则会停止等待,继续执行,并返回true。

如果当前线程没有获得permits个许可证,也会停止等待,继续执行,并返回false。

——tryAcquire(timeout,TimeUnit)

当前线程在限定时间内,阻塞的尝试去获取1个许可证。

此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:

当前线程获取了可用的许可证,则会停止等待,继续执行,并返回true。
当前线程等待时间timeout超时,则会停止等待,继续执行,并返回false。
当前线程在timeout时间内被中断,则会抛出InterruptedException一次,并停止等待,继续执行。
——tryAcquire(permits,timeout,TimeUnit)

当前线程在限定时间内,阻塞的尝试去获取permits个许可证。

此过程是阻塞的,它会一直等待许可证,直到发生以下任意一件事:

当前线程获取了可用的permits个许可证,则会停止等待,继续执行,并返回true。
当前线程等待时间timeout超时,则会停止等待,继续执行,并返回false。
当前线程在timeout时间内被中断,则会抛出InterruptedException一次,并停止等待,继续执行。
——release()

当前线程释放1个可用的许可证。

——release(permits)

当前线程释放permits个可用的许可证。

——drainPermits()

当前线程获得剩余的所有可用许可证。

——hasQueuedThreads()

判断当前Semaphore对象上是否存在正在等待许可证的线程。

——getQueueLength()

获取当前Semaphore对象上是正在等待许可证的线程数量。

(多线程)leetcode1117. H2O 生成 认识Java中的PV原语相关推荐

  1. java fields是_一个快速生成R2.java中fields的插件

    一个快速生成R2.java中fields的插件 项目地址:github.com/JeasonWong/- 介绍 在子 module 中使用 ButterKnife 时,如果想使用 ButterKnif ...

  2. LeetCode 多线程 1117. H2O 生成

    1117. H2O 生成 Ideas 虽然题目中给出了多种答案,不过我们可以限制一下各个线程输出的顺序,让输出结果的顺序只能是HHO. 我们可以设置两个信号量,hydrogenSema = Semap ...

  3. java 指针_java多线程学习二十二:::java中的指针

    在上面那个图,我们看到一个特殊的变量unsafe,它的包名是 sun.misc.Unsafe;从名字看,这个类应该是封装一些不安全的操作,为什么不安全?对c语言理解的朋友就知道了,指针是不安全的,在j ...

  4. 用java线程绘制图案_关于多线程:使用线程在java中绘制面板

    我正在编写一个包含许多不同视图的程序. 其中一个是相当图形密集型(它显示一个互连的图形). 其他人只是展示小而复杂的图表. 我发现主视图的绘制时间很长(甚至只绘制当前可见的区域),并且在绘制时,界面的 ...

  5. Android多线程研究(8)——Java中的原子性理解

    一.什么是原子性 原子性是世界上最小单位,具有不可分割性.比如a=0;(a非long和double类型)这个操作是不可分割的,那么我们说这个操作是原子操作.再比如:a++;这个操作实际上是a=a+1; ...

  6. java 随机生成图,Java中的快速实值随机生成器

    java.util.Random.nextDouble() is slow for me and I need something really fast. I did some google sea ...

  7. java中的pv操作,PV操作简单理解

    进程通常分为就绪.运行和阻塞三个工作状态.三种状态在某些条件下可以转换,三者之间的转换关系如下: 进程三个状态之间的转换就是靠PV操作来控制的.PV操作主要就是P操作.V操作和信号量.其中信号量起到了 ...

  8. java中实现多线程的三种方式

    java中实现多线程的三种方式 1.实现多线程的方法: 在java中实现多线程的两途径:继承Thread类,实现Runable接口(Callable) 2.继承Thread类实现多线程: ​ 继承类T ...

  9. java中sleep()、wait()相同与不同详解

    java中sleep().wait()相同与不同详解 相同 java中Thread#sleep和Object#wait方法都是暂停当前线程,当前线程让出CPU占用.并不存在调用sleep后还占用CPU ...

最新文章

  1. sed linux 命令
  2. mysql语句优化百条_优化mysql语句
  3. 多元函数概念思维导图_高等数学 多元函数微分学 知识技巧思维导图 [21考研上岸之旅]...
  4. 【渝粤题库】陕西师范大学152102 管理学原理作业(高起专)
  5. mysql数据超10亿条,大型主键:超过10亿行MySQL + InnoDB?
  6. 曾比海底捞还牛,如今关店1200家!肯德基的猪队友,快被中国人抛弃了?
  7. Mysql 分区(range,list,hash)转载
  8. 通过Git WebHooks+脚本实现自动更新发布代码之Shell脚本(二)
  9. 拓端tecdat|R语言广义二次跳跃、非线性跳跃扩散过程转移函数密度的估计及其应用
  10. php smarty 调试模式,Smarty3调试
  11. 【教程】 如何在linux/mac下安装pascal
  12. [深度学习概念]·深度学习的人脸识别技术发展综述
  13. win10定时锁定计算机,Win10自动锁屏时间太长了怎么设置?Win10设置自动锁屏时间的操作...
  14. excel查找空值快捷键_Excel之定位和查找(一)
  15. 关于iis中域名转向的问题
  16. 达人评测 惠普暗影精灵8和惠普暗影精灵8plus的区别
  17. 揭秘网站的seo技术 ---seo与seoer 王泽宾
  18. 建设GSM900/1800双频网应考虑的几个问题(转)
  19. 30分钟搞定极光sdk安卓客户端接入
  20. xHCI1.1-USB设备的初始化

热门文章

  1. yytextview多种格式_iOS YYText的使用笔记一(YYTextView图文编辑器)
  2. 专业程序员必知必会的技巧:驯服复杂代码
  3. c语言内循环,C语言循环控制语句
  4. ashx连接mysql_对C#中的web访问mysql数据库的一些知识点进行了整理归纳总结
  5. 【转】DICOM通信 - PDU数据包(2)
  6. 【转】Dicom格式文件解析器!!!!!!!
  7. .net开源框架简介和通用技术选型建议
  8. TFS中的工作项(六)
  9. 由浅到深理解ROS(1)
  10. mysql实验三单表和多表查询_数据库实验三(单表查询)