Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么是java';s相当于手动重置事件?_Java_.net_Multithreading_Synchronization - Fatal编程技术网

什么是java';s相当于手动重置事件?

什么是java';s相当于手动重置事件?,java,.net,multithreading,synchronization,Java,.net,Multithreading,Synchronization,java的等价物是什么?据我所知,最接近的是。只要在“许可”计数为1的情况下使用它,获取/释放将与您从ManualResetEvent中了解到的内容几乎相同 初始化为1的信号量,以及 它的使用使得它只在 大多数情况下,一个许可证可用 作为互斥锁。这是 通常称为二进制 信号量,因为它只有两个 州:一个许可证可用,或零 许可证可用。当用于此 这样,二进制信号量具有 属性(与许多锁不同 实现),即“锁”可以 由线程以外的线程释放 所有者(因为信号量没有 所有权)。这在某些情况下很有用 特殊上下文,如死

java的等价物是什么?

据我所知,最接近的是。只要在“许可”计数为1的情况下使用它,获取/释放将与您从
ManualResetEvent
中了解到的内容几乎相同

初始化为1的信号量,以及 它的使用使得它只在 大多数情况下,一个许可证可用 作为互斥锁。这是 通常称为二进制 信号量,因为它只有两个 州:一个许可证可用,或零 许可证可用。当用于此 这样,二进制信号量具有 属性(与许多锁不同 实现),即“锁”可以 由线程以外的线程释放 所有者(因为信号量没有 所有权)。这在某些情况下很有用 特殊上下文,如死锁 恢复

基于:

ManualResetEvent允许线程通过以下方式相互通信: 信号。通常情况下 沟通涉及的任务 一个线程必须在另一个线程之前完成 线程可以继续

从这里开始:

您可能想看看Java并发包中的障碍——具体地说,CyclicBarrier我相信:

它会阻止固定数量的线程,直到发生特定事件。所有螺纹必须在障碍点处连接在一起

尝试计数一

CountDownLatch startSignal = new CountDownLatch(1);

我相信.NETMRE的关键在于线程亲和力,以及它在调用Set时让所有等待的线程通过的能力。我发现信号灯的使用效果很好。然而,如果我有10或15个线程等待,那么我会遇到另一个问题。具体来说,它发生在调用Set时。在.Net中,所有等待的线程都被释放。使用semphore并不能释放所有。所以我把它包装在一个班级里。注意:我非常熟悉.NET线程。我对Java线程和同步比较陌生。尽管如此,我还是愿意参与进来,并得到一些真正的反馈。下面是我的实现,其中假设Java新手会:

public class ManualEvent {
private final static int MAX_WAIT = 1000;
private final static String TAG = "ManualEvent"; 
private Semaphore semaphore = new Semaphore(MAX_WAIT, false);

private volatile boolean signaled = false;
public ManualEvent(boolean signaled) {
    this.signaled = signaled; 
    if (!signaled) {
        semaphore.drainPermits();
    }
}

public boolean WaitOne() {
    return WaitOne(Long.MAX_VALUE);
}

private volatile int count = 0;
public boolean WaitOne(long millis) {
    boolean bRc = true;
    if (signaled)
        return true;

    try {
        ++count;
        if (count > MAX_WAIT) {
            Log.w(TAG, "More requests than waits: " + String.valueOf(count));
        }

        Log.d(TAG, "ManualEvent WaitOne Entered");
        bRc = semaphore.tryAcquire(millis, TimeUnit.MILLISECONDS);
        Log.d(TAG, "ManualEvent WaitOne=" + String.valueOf(bRc));
    }
    catch (InterruptedException e) {
        bRc = false;
    }
    finally {
        --count;
    }

    Log.d(TAG, "ManualEvent WaitOne Exit");
    return bRc;
}

public void Set() {
    Log.d(TAG, "ManualEvent Set");
    signaled = true;
    semaphore.release(MAX_WAIT);
}

public void Reset() {
    signaled = false;
    //stop any new requests
    int count = semaphore.drainPermits();
    Log.d(TAG, "ManualEvent Reset: Permits drained=" + String.valueOf(count));
}
}


还请注意,我基本上是在打赌,在任何给定的时间,等待发布的请求不会超过1000个。通过批量发布和获取,我试图释放任何等待的线程。请注意,对WaitOne的调用一次只能使用1个许可证。

我认为如果没有争用条件(假设线程无法释放它以前没有获取的信号量),这是不可行的。我收回了它-从文档中可以看出,信号量可以在不使用它的情况下释放。是的,这是因为信号量没有所有权概念。它们几乎都是同步计数器,如果计数器为0,线程将等待。如果在没有适当的获取的情况下多次释放信号量,则AvailablePermits将大于1,并且其行为方式与ManulReseteEvent不同,因为reset()不会导致waitOne()等待。@Agent\L您当然是正确的,需要立即
释放
,它才能模仿
手动重置事件
,否则您将拥有一个
自动重置事件
。正如我所写的,这只是我所知道的Java中最接近的同步原语。
ManualResetEvent
的一个常见用法是一个线程等待同步,该用例不会出现微阻塞(只有当多个线程在事件中同时等待时才会发生),开销应该相当小(与另一个答案中提供的监控解决方案相当).倒计时闩锁的问题是它不能重复使用。一旦闩锁达到0,它就不能再使用了。它可以替换为一个新的闩锁实例,但这会创建争用条件,除非操作正确。这看起来根本不起作用:线程一调用
waitOne()
并在
monitor.wait()
中阻塞。执行两个调用
set
并在
synchronized(monitor)
上阻塞。这是唯一的用例,对吗?我认为,如果您在
set
@limitedAtoniment中省略
synchronized
语句是可以的:在Java中,您必须在同步块中才能等待对象。在等待期间,该对象的监视器锁被释放,因此可以在另一个线程中获取它。见@WayneUroda我的坏。我想我不应该问你为什么一个人必须在
synchronized
块中才能通过调用
wait
释放锁。我敢肯定那是老掉牙的@在其他语言中,您可以在类似实体上等待/通知,而不必锁定它们(C#IIRC、win32/GDI等)。我认为用java这样做是为了帮助程序员避免一些常见的竞争条件。也许这比我能更好地解释:)它的工作很好!以及它在java中的正确实现ManualResetEvent。所有其他的实现或坏的或复杂的为什么不看看另一个最好的答案?你能提供一些障碍的例子吗?我没有从文档中得到这个例子。哦,我找到了一篇文章:所以它会阻塞,直到所有线程都达到屏障(所以形成临界质量),然后它会继续。很有趣。现在我知道这件事了。不幸的是,对于这个问题,它并没有太大用处,但它是这样来的,每个java对象都有wait,shich是ManualResetEvent@BogdanMart但它会自动重新阻塞,这意味着它既不是
ManualResetEvent
也不是
AutoResetEvent
@BogdanMart我不是在谈论其他答案。我是说你的评论不真实,误导了其他读者。
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 boolean waitOne(long milliseconds) throws InterruptedException {
    synchronized (monitor) {
      if (open) 
        return true;
      monitor.wait(milliseconds);
        return open;
    }
  }

  public void set() {//open start
    synchronized (monitor) {
      open = true;
      monitor.notifyAll();
    }
  }

  public void reset() {//close stop
    open = false;
  }
}