Последние два потока ожидают уведомления, используя экземпляр ThreadPoolAsynchronousRunner
в качестве монитора, поэтому источник этого будет выглядеть примерно так:
synchronized(asyncRunner) {
// ...
asyncRunner.wait();
// ...
}
Как только вы вызываете wait
, синхронизация на asyncRunner
«освобождается», то есть другие части приложения могут вводить блок, который синхронизируется в этом экземпляре. В вашем конкретном случае кажется, что это произошло, и был возвращен вызов wait
первого потока, и в настоящее время он обрабатывает некоторые данные, которые поступают из него. Вы по-прежнему видите несколько locked
-линий в дампе потока, чтобы показать вам, что код в настоящее время находится в synchronized
-блоке, но, как уже было сказано, «блокировка» освобождается при вызове wait
.
Техника, которую вы видите здесь как дамп потока, довольно распространена до того, как concurrent-пакет был добавлен в JDK, чтобы избежать дорогостоящих созданий потоков. И ваш поток-дамп выглядит как этот вид реализации. Вот простая реализация, как это может выглядеть "под капотом":
// class ThreadPoolAsynchronousRunner
private Deque<AsyncMessage> queue;
public synchronized void addAsyncMessage(AsyncMessage msg) {
queue.add(msg);
notifyAll();
}
public void start() {
for (int i = 0; i < 4; i++) {
PoolThread pt = new PoolThread(this);
pt.start();
}
}
ThreadPoolAsynchronousRunner`` запускает PoolThreads и выполняет notifyAll
, если добавляется новое обрабатываемое сообщение.
// PoolThread
public PoolThread(ThreadPoolAsynchronousRunner parent) {
this.parent = parent;
}
public void run() {
try {
while (true) {
AsyncMessage msg = null;
synchronized(parent) {
parent.wait();
if (!parent.queue.isEmpty()) {
msg = queue.removeFirst();
}
}
if (msg != null) {
processMsg(msg);
}
}
}
catch(InterruptedException ie) {
// exit
}
}
notifyAll
приведет к возврату всех wait
-методов всех потоков, поэтому вы должны проверить, содержит ли очередь в родительском элементе данные (иногда wait
возвращается даже без уведомления, поэтому вам нужно эта проверка, даже если не используется notifyAll
). Если это так, вы запускаете метод обработки. Вы должны делать это за пределами synchronized
-блока, иначе ваш класс асинхронной обработки обрабатывает только одно сообщение за раз (если только это не то, что вы хотите - но тогда зачем запускать несколько PoolThread
-инстанций?)