(問題は解決しました。以下の解決策)
2 つのクラスがあります。Equip と Command です。装備はコマンドを実行する装備ですが、同時に1つのコマンドしか実行できないようにする必要があります。コマンドは 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のおかげで、エグゼキューターを使用して、別のまったく異なるアプローチを使用して問題を解決しました。
これが最終的なコードです。いつか誰かを助けるかもしれません:
装備クラス:
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 クラスには、装備の execute メソッドをカプセル化するメソッドがあります。ブール型の waitCompletion は、コマンドの結果が同時に必要な場合に使用されます。新しいスレッドを呼び出して実行する代わりに、同じスレッドで実行されているふりをして、実行して待機するだけです。この質問には、この問題に関する適切な議論が含まれています。. はい、これは .start() の代わりに .run() を呼び出すと便利な場合です。