В вашем случае проблема в том, что
System.out.println(deque.takeLast());
на самом деле две инструкции, которые вместе не являются атомарными.Представьте себе такой сценарий:
- Поток 1 получает строку из очереди.
- Поток 2 принимает строку из очереди.
- Поток 2 печатает значение.
- Поток 1 выводит значение.
Так что все зависит от того, как операционная система будет управлять выполнением потоков.
В вашем случае одним из возможных решений было бы добавить ключевое слово synchronized
к run
method:
Runnable rb = new Runnable() {
public synchronized void run() {
try {
String s = deque.takeLast();
System.out.println(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Это будет синхронизироваться с экземпляром анонимного класса, который вы создали здесь.Так как вы передаете тот же runnable ExecutorService - он должен работать.Или вы можете синхронизировать ваш queue
объект, поскольку ваш runnable, который имеет доступ к объекту очереди, будет выполняться во многих потоках, так как вы передали его в ExecutorService
:
Runnable rb = new Runnable() {
public void run() {
synchronized (deque) {
try {
String s = deque.takeLast();
System.out.println(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Также помните о закрытииваш пул потоков, потому что теперь ваше приложение никогда не выйдет.