(問題已解決,解決方案如下)
我有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