(问题已解决,解决方案如下)
我有 2 个课程:装备和指挥。装备是运行命令的设备,但我需要它能够同时运行一个命令。命令是一个线程,它在 run() 函数上执行,而 Equip 是一个不扩展任何东西的普通类。目前我有以下设置来运行命令:
命令类:
@Override
public void run() {
boolean execute = equip.queueCommand(this);
if (!execute) {
// if this command is the only one on the queue, execute it, or wait.
esperar();
}
// executes the command.....
equip.executeNextCommand();
}
synchronized public void esperar() {
try {
this.wait();
} catch (Exception ex) {
Log.logErro(ex);
}
}
synchronized public void continue() {
this.notifyAll();
}
装备等级:
public boolean queueCommand(Command cmd) {
// commandQueue is a LinkedList
commandQueue.addLast(cmd);
return (commandQueue.size() == 1);
}
public void executeNextCommand() {
if (commandQueue.size() >= 1) {
Command cmd = commandQueue.pollFirst();
cmd.continue();
}
}
但是,这是行不通的。基本上, notify() 不会唤醒命令线程,因此它永远不会执行。我搜索了等待和通知协议,但我找不到代码有什么问题。我也尝试直接从 queueCommand() 方法调用 wait() ,但随后 queueCommand 的执行停止了,它也没有做它应该做的事情。这种方法是否正确,我遗漏了什么,或者这是完全错误的,我应该实现一个 Monitor 类来操作并发线程?
编辑:感谢@Gray,我使用另一种完全不同的方法解决了这个问题,使用 Executors。
这是最终的代码,有一天它可能会对某人有所帮助:
装备等级:
private ExecutorCompletionService commandQueue = new ExecutorCompletionService(Executors.newFixedThreadPool(1));
public void executeCommand(Command cmd, boolean waitCompletion) {
commandQueue.submit(cmd, null);
if (waitCompletion) {
try {
commandQueue.take();
} catch (Exception ex) {
}
}
}
在 Command 类中,我只有一个方法来封装设备的执行方法。当我同时需要命令的结果时使用布尔值 waitCompletion,而不是调用一个新线程来执行它,我只是执行并等待,假装它在同一个线程上执行。这个问题包含一个关于这个问题的很好的讨论:你什么时候调用java的thread.run()而不是thread.start()?. 是的,在这种情况下,调用 .run() 而不是 .start() 很有用。