如何让Java线程通知自己?

时间:2013-01-24 20:57:53

标签: java multithreading

我有一个Thread来处理队列中的操作。基本上,循环永远。如果队列中有操作,则使操作出列并执行。如果没有操作,请等到你被告知有。

在伪代码中(暂时忽略关键部分):

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

基本上,Controller类会初始化此OperationHandlerstart()。每当有些请求到达时,控制器就会在线程上调用operationRequired,以便在无限while循环中异步处理操作。有没有办法实现这个目标?

我尝试使用this.wait()this.notify(),但我会遇到死锁或IllegalMonitorStateException,具体取决于不同的同步块。

4 个答案:

答案 0 :(得分:8)

  

如何让Java线程通知自己?

您无法让线程通知自己,因为它已在wait()中被阻止。 可以让另一个线程通过同步线程锁定的同一个对象并调用notify()来通知线程。请参阅以下代码以获取示例。

那就是说,我建议使用BlockingQueue来分享这方面的数据。它负责所有的锁定和信号。所有线程都调用take(),它将等待下一个操作添加到put()的队列。

最后,始终建议实施Runnable而不是扩展Thread。将线程转换为runnable后,您可以在其答案中使用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 :(得分:2)

如果在没有线程等待()时通知(),则忽略它。即一个线程通知自己是没有意义的,因为它不能等待并同时通知。

如果你有一个队列和线程,你应该使用一个包装它们的ExecutorService。 BTW它使用BlockingQueue

答案 2 :(得分:1)

如果等待,则无法使用相同的线程调用operationRequired方法。虽然它在同一个线程类中,但它很可能是用另一个线程执行的。

因此,请使用正常同步:首先使用synchronized输入监视器,然后等待或通知。另一种选择是使用java.util.concurrent.*的队列。他们在内部支持这些东西。

答案 3 :(得分:0)

使用BlockingQueue及其take()操作。它已经等待并通知嵌入式内部。

相关问题