2012-06-01 31 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

相關問題