(问题已解决,解决方案如下)
我有2个类:装备和命令。装备是一个运行命令的设备,但我需要它能够同时运行一个命令。 命令是一个线程,它在run()函数上执行,而Equip是一个不扩展任何东西的普通类。 目前,我有以下设置来运行命令:控制线程使用wait()和notify()
Command类:
@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()不会唤醒命令线程,所以它永远不会执行。 我搜索了wait和notify协议,但是我找不到任何代码错误。我也试着直接从queueCommand()方法中调用wait(),但是然后queueCommand的执行停止了,它也没有做它应该做的事情。 这种方法是否正确,我错过了一些东西,或者这是完全错误的,我应该实现一个Monitor类来处理并发线程?
编辑:我使用另一种完全不同的方法解决了问题,使用了Executors,感谢@Gray。
下面是最后的代码,它可能会帮助别人一天:
装备类:
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) {
}
}
}
在命令类我只需要封装装备的执行方法的方法。 当我需要命令的结果的同时使用布尔型的waitCompletion,而不是调用一个新线程来执行它,我只是执行并等待,假装它在同一个线程上执行。这个问题包含了关于这个问题的一个很好的讨论:When would you call java's thread.run() instead of thread.start()?。是的,这是一个调用.run()而不是.start()的情况。
我们在这里讨论的每种线程有多少种?在这段代码中至少有一些不好的竞争条件,可能会导致意想不到的行为,如果每种类型中有超过1个,就会看到这种行为。 – Gray 2012-03-08 19:59:18
'commandQueue'是一个TreeSet吗?它是同步的吗? – Gray 2012-03-08 20:02:03
Equip类没有任何子类,但有几种类型的Command。我不认为这是一个问题,通常也只有1或2个命令同时执行。我只是这样做的,因为如果2个命令在同一时间执行,事情可能会出错,他们将无法正确执行(由于我的解决方案的复杂性,设备实际上是一个通过运行C代码的UDP控制的机器)。 – 2012-03-08 20:03:18