C# Java与.NET的等价物';s ManualResetEvent和WaitHandle
我想知道Java是否提供了与.NET的ManualResetEvent和WaitHandle类等价的类,因为我想编写代码,除非触发事件,否则会在给定的超时时间内阻塞C# Java与.NET的等价物';s ManualResetEvent和WaitHandle,c#,java,.net,eclipse,synchronization,C#,Java,.net,Eclipse,Synchronization,我想知道Java是否提供了与.NET的ManualResetEvent和WaitHandle类等价的类,因为我想编写代码,除非触发事件,否则会在给定的超时时间内阻塞 WaitHandle和ManualResetEvent的.NET类提供了一个很好的、无麻烦的接口,据我所知,它也是线程安全的,那么Java提供了什么呢?您是否考虑过使用wait/notify(相当于Monitor.wait和Monitor.Pulse) 你需要一点检查,看看你是否真的需要等待(以避免比赛条件),但它应该会起作用 否则
WaitHandle和ManualResetEvent的.NET类提供了一个很好的、无麻烦的接口,据我所知,它也是线程安全的,那么Java提供了什么呢?您是否考虑过使用
wait
/notify
(相当于Monitor.wait
和Monitor.Pulse
)
你需要一点检查,看看你是否真的需要等待(以避免比赛条件),但它应该会起作用
否则,像这样的事情很可能会做你想做的
编辑:我刚刚注意到,CountDownLatch
基本上是“一次性使用”——据我所知,您以后不能重置计数。你可能会想要。像这样使用tryAcquire
等待超时:
if (semaphore.tryAquire(5, TimeUnit.SECONDS)) {
...
// Permit was granted before timeout
} else {
// We timed out while waiting
}
请注意,这与ManualResetEvent
不同,因为每次成功调用tryAcquire
都会减少许可证的数量,因此最终它们会再次用完。您不能像使用ManualResetEvent
一样将其永久“设置”。(这将与倒计时闩锁一起工作,但是您无法“重置”它:)来自:
您好,您可以使用java.util.concurrent.Semaphore类(使用0 permit)实现同步
下面的示例演示如何解决第一个同步问题,另一个类似:
import java.util.concurrent.Semaphore;
class ScalesCommunication {
private static Semaphore sem = new Semaphore(0);
// called by thread 1
void readLoop() {
//...
//after connection established, release semaphore (value incremented by 1)
sem.release();
}
// called by thread 2
String sendCommand(String command) {
sem.acquire(); // thread waits here if sem value == 0
// at this point connection is established
//...
}
}
理论上,上面给出的ManualResetEvent类在Java 5上是正确的(但不是更早)。考虑到volatile的不正确(或不充分)实现有很长的历史,我认为在reset()中添加一个额外的同步块更明智,以便生成一个有保证的写屏障,并确保完整的原子性。危险在于,在多处理器Intel CPU上读取“open”可能会传递写入“open”。下面给出的更改的优点:它可能不是最有效的,但它确实有很大的优点,可以保证不会出错,只需很少的额外成本
class ManualResetEvent {
private final Object monitor = new Object();
private volatile boolean open = false;
public ManualResetEvent(boolean open) {
this.open = open; }
public void waitOne() throws InterruptedException {
synchronized (monitor) {
while (open==false) {
monitor.wait();
}
}
}
public void set() {//open start
synchronized (monitor) {
open = true;
monitor.notifyAll();
}
}
public void reset() {//close stop
synchronized(monitor) {
open = false;
}
}
}
多亏了原来的海报 但是超时方面呢?从我在CountDownLatch的文档中读到的内容来看,它似乎没有一个超时值,我可以在超时运行到最后之前拦截或停止它。我希望有一个Java类型,我可以使用它来等待超时,并且可以在超时结束之前拦截它,比如手动覆盖。还有,你好,斯基特先生!你好吗?你可能会得到很多,但你的书很棒@Voulnet:您可以调用
wait(长超时,时间单位)
——它将在给定的超时持续时间内阻塞,或者在锁存器倒计时为0时更早返回。很高兴你喜欢这本书:)是的,这个解决方案一定很有效,因为我在任何时候都只有一个对象在等待。谢谢,Jon Skeet先生。请注意,这包含一个严重的错误:如果在set()
之前调用waitOne()
,则将输入监视器,因此对set()
的调用将被阻止,从而导致死锁。我的黑客解决方案是在循环中调用monitor.wait(10)
,该循环每次迭代都会退出同步。实际上,我可能错了,因为显然应该在等待期间释放监视器,尽管我的测试显示出明确的死锁。不管怎样,我已经切换到在我的用例中使用信号灯
。你能用死锁进行测试吗?事实上,问题是当ManualResetEvent打开时,所有线程都应该唤醒吗?尽管我看起来也很怀疑。可以。
class ManualResetEvent {
private final Object monitor = new Object();
private volatile boolean open = false;
public ManualResetEvent(boolean open) {
this.open = open; }
public void waitOne() throws InterruptedException {
synchronized (monitor) {
while (open==false) {
monitor.wait();
}
}
}
public void set() {//open start
synchronized (monitor) {
open = true;
monitor.notifyAll();
}
}
public void reset() {//close stop
synchronized(monitor) {
open = false;
}
}
}