1

我有一组方法说m1, m2, m3, m4. 每个都需要等待上一个方法完成。如果我打电话m3,它必须等待m2。我想为每种方法使用标志,如果完成标记它。但是对于通知,如果m1notify(),我只希望这个通知m2,而不是其他等待方法。

我有一个组件A, m1,作为输入方法和m2输出方法。一旦发生,它将调用产生输出。但是, ,必须按顺序执行,并且可以从不同的类中调用。必须有等待和相应的信号。m3m4m3m4m1m2m3

我该如何实施呢?

4

5 回答 5

2

BlockingQueues 可能会有所帮助,但如果您使用的是 ThreadPoolExecutor,则不会。ThreadPoolExecutor 没有提供开箱即用的解决方案来阻止队列已满(这是执行程序的一部分,不是队列的功能,因为执行程序使用 BlockingQueue.offer 永远不会阻塞,如果队列是完全使用 RejectedExecutionHandler)。您可以实现自己的 RejectedExecutionHandler 阻塞,直到它可以将东西放入队列中,但这是一种使用锁的快速确定方法:

ReentrantLock l1 = new ReentrantLock();
ReentrantLock l2 = new ReentrantLock();
ReentrantLock l3 = new ReentrantLock();

l1.lock();
l2.lock();
l3.lock();


// pass l1,l2,l3 along to the threads running these methods, so they are available to the methods:

public void m1() {
 try {
  // do stuff
 }
 finally {
   l1.unlock();
 }
}

public void m2() {
 l1.lock();
 try {
  // do stuff
 }
 finally {
   l2.unlock();
 }
}

public void m3() {
 l2.lock();
 try {
  // do stuff
 }
 finally {
   l3.unlock();
 }
}

public void m4() {
 l3.lock();
 // do stuff
}
于 2012-06-01T12:57:47.697 回答
1

你不想要锁,但屏障: m(n + 1) 必须等到 m(n) 被调用。下面的代码假设只有一个序列或方法调用(并且 m1/2/3 从不同的线程调用或在同一线程上以正确的顺序调用,否则您将永远等待闩锁)。如果它可以发生多次,则需要重新设置(或者您可以使用 Phaser 来获得灵感)。

private CountDownLatch m2latch = new CountDownLatch(1);
private CountDownLatch m3latch = new CountDownLatch(1);

public void m1() {
  // handle input
  m2latch.countDown();
}

public void m2() {
  m2latch.await();
  // handle input (m1 has been called)
  m3latch.countDown();
}

public void m3() {
  m3latch.await();
  // do output (both m1 + m2 have been called)
}

然而,这有点奇怪的设计,因为你想按顺序做,你应该只在输出方法中完成所有工作,它会等到所有输入都输入。

 private CountDownLatch inputLatch = new CountDownLatch(3);
 private Object[] input = new Object[3];

 public void setInput(int i, Object data) {
   input[i] = data;
   inputLatch.countDown(); // perhaps better check all input set
 }

 public Object processInput() {
   inputLatch.await();
   return process(input); // process in sequence
 }
于 2012-06-01T14:39:15.817 回答
0

我会将计数器设置为 int,并且每种方法都必须等到计数器达到它们的数字才能使用。这样,每个方法只需要增加计数器,您可以稍后插入更多。

于 2012-06-01T12:54:27.347 回答
0

一个简单的解决方案是只使用四个不同的锁对象。(或者确实在同一个线程中运行它们,但这可能不是你想要的。)

有了更多细节,可能会有更优雅的解决方案。

于 2012-06-01T12:56:13.297 回答
0

我的建议是那个,取决于我是否正确理解了这个问题:

public void m4() {
    m3();
    do something;
}

public void m3() {
    m2();
    do something;
}

public void m2() {
   m1();
   do something;
}

public void m1() {
   do something;
}
于 2012-06-01T13:04:00.020 回答