(проблема решена, решение приведено ниже)
У меня 2 класса: экипировка и командование. Оборудование - это оборудование, которое запускает команды, но мне нужно, чтобы оно могло выполнять только 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 () не пробуждает поток команд, поэтому он никогда не будет выполнен.
Я искал протокол ожидания и уведомления, но не смог найти ничего плохого в коде. Я также попытался вызвать wait () напрямую из метода queueCommand (), но затем выполнение queueCommand прекратилось, и он также не сделал то, что должен был сделать.
Является ли этот подход правильным, и я что-то упускаю, или это совершенно неправильно, и я должен реализовать класс Monitor для управления параллельными потоками?
РЕДАКТИРОВАТЬ: Я решил проблему, используя другой совершенно другой подход, используя Executors, благодаря @ Grey.
Вот окончательный код, он может кому-нибудь когда-нибудь помочь:
Класс экипировки:
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 из equip.
Логическое значение waitCompletion используется, когда мне одновременно нужен результат команды, и вместо вызова нового потока для его выполнения я просто выполняю и жду, делая вид, что выполняется в том же потоке. Этот вопрос содержит хорошее обсуждение по этому вопросу: Когда бы вы вызвали java's thread.run () вместо thread.start ()? . И да, это тот случай, когда полезно вызывать .run () вместо .start ().