2012-06-01 98 views
1

我有一套方法说m1,m2,m3,m4。每个人都需要等待以前的方法才能完成。如果我拨打m3,它必须等待m2。我想为每种方法使用标志,如果完成了标记。但通知,如果m1notify(),我只想通知m2,而不是其他等待方法。如何在java中实现另一种方法的等待方法?

我有一个部件A,其具有m1m2m3作为输入的方法和m4作为输出方法。一旦m3发生,它会呼叫m4产生输出。但是m1,m2,m3必须按顺序执行并且可以从不同的类中调用。等待和相应的信号必须在那里。

我该如何去实现它?

+2

你只需要m1,m2,m3和m4按顺序执行,每个等待前一个?只要做到: m1(); m2(); m3(); m4(); 虽然我猜你想要稍微不同的事情发生。你能解释我上面写的是不是做你想做的? –

+0

我不知道为什么,但这种回忆我Observer模式... – davioooh

+0

我不明白这一点,如果他们彼此等待,只需一个接一个地执行。 – nyyrikki

回答

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 
} 
0

我会设置一个计数器作为一个整数,每个方法必须等到计数器到达之前,他们可以去。这样,每种方法只需增加计数器,并可以稍后插入。

+0

是不是基本上是一个'信号灯'? – biziclop

+0

是的,等待部分没有问题,但是如果一旦完成之前的方法,如何发出等待方法执行信号。不想定期检查。 – gondpk

0

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

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

+0

刚刚更新了问题。 – gondpk

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 
} 
+0

ps:如果您想要任意数量的方法,您可以始终使用ReentrantLock数组,并将两个锁传递给每个方法。一个锁定开始,一个解锁完成(考虑到它们可能为空而无所事事)。 – Matt

+0

检查出来,将更新结果:) – gondpk

0

我的建议是一个,如果我理解正确的问题在于:

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

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

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

public void m1() { 
    do something; 
} 
+0

是的,这是一件很直白的事情。更新了问题。 – gondpk

相关问题