2013-01-24 42 views
1

我有一個處理隊列中的操作的線程。基本上,永遠循環。如果隊列中有操作,則使操作出列並執行。如果沒有任何操作,請等到有人告訴您。如何獲得Java線程來通知自己?

在僞代碼(忽略現在關鍵段):

public class OperationHandler extends Thread { 
    private Deque<Operation> queue = new LinkedList<>(); 
    public void run() { 
     while (true) { 
      if (queue isn't empty) { 
       dequeue the operation and execute it 
      } 
      else { 
       wait; 
      } 
     } 
    } 

    public void operationRequired() { 
     add operation to queue 
     notify yourself/return to infinite while loop 
    } 
} 

基本上控制器類初始化此OperationHandlerstart()這樣。每當有一些請求到達時,控制器會在線程上調用operationRequired,以便在無限循環中異步處理操作。有什麼辦法可以做到這一點?

我試過this.wait()this.notify()但我得到死鎖或IllegalMonitorStateException取決於不同的同步塊。

+0

你不能。這個問題沒有意義。您正在討論一個線程,但也涉及異步操作。你真的有至少兩個線程。請修改你的問題,這是有道理的。 – EJP

+0

'operationRequired()'是從另一個線程調用的。 –

回答

8

如何讓Java線程通知自己?

因爲在wait()中被阻止,所以無法通知主題。您可以可以有另一個線程通過同步線程鎖定的同一個對象來通知線程,並調用notify()。有關示例,請參閱下面的代碼。

也就是說,我建議使用BlockingQueue來共享這方面的數據。它負責所有的鎖定和信號。所有線程都會調用take(),並且它將等待下一個操作被添加到隊列中,使用put()

最後,總是推薦實施Runnable而不是擴展Thread。一旦你把你的線程變成可運行的,你可以使用ExecutorService類作爲@Peter在他的答案中提到。隨着ExecutorService你的代碼看起來像:

public class OperationHandler implements Runnable { 
    public void run() { 
     // no looping or dequeuing needed 
     // just execute the job 
    } 
} 

// create a thread pool with a single thread worker 
ExecutorService threadPool = Executors.newSingleThreadExecutor(); 
// or create a thread pool with 10 workers 
// ExecutorService threadPool = Executors.newFixedThreadPool(10); 
// or you can create an open-ended thread pool 
// ExecutorService threadPool = Executors.newCachedThreadPool(); 
... 
// do this once or many times 
threadPool.submit(new OperationHandler()); 
... 

但是,如果你仍然想調整你的代碼來得到它的工作:

private final Object lockObject = new Object(); 
    public void run() { 
    synchronized (lockObject) { 
     ... 
     lockObject.wait(); 
    } 
    } 

    // called by another thread 
    public void operationRequired() { 
    synchronized (lockObject) { 
     ... 
     lockObject.notify(); 
    } 
    } 
+1

...這就是爲什麼你想要一個BlockingQueue,take()會阻塞,直到其他線程提供一些工作。所有這些都很好地包裝在一個ExecutorService中。 –

+1

+1。 Runnable也將允許你使用ExecutorServices –

+2

+1坦率地說,OP看起來毫無意義地重新實現ExecutorService –

2

如果你通知()時,有沒有線程等待( )它被忽略。即線程通知自己是沒有意義的,因爲它不能等待並同時通知。

如果你有一個隊列和線程,你應該使用一個包裝兩者的ExecutorService。順便說一句,它使用BlockingQueue

1

您的operationRequired方法不能用同一個線程調用,如果它正在等待。雖然它在同一個線程類中,但它很可能會在另一個線程中執行。

所以使用正常同步:先用​​進入監視器,然後等待或通知。另一種選擇是使用隊列形式java.util.concurrent.*。他們內部支持這些東西。

0

Usa a BlockingQueue及其take()操作。它已經等待並通知嵌入。

相關問題