我有一个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类会初始化此OperationHandler
和start()
。每当有些请求到达时,控制器就会在线程上调用operationRequired
,以便在无限while
循环中异步处理操作。有没有办法实现这个目标?
我尝试使用this.wait()
和this.notify()
,但我会遇到死锁或IllegalMonitorStateException
,具体取决于不同的同步块。
答案 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()
操作。它已经等待并通知嵌入式内部。