Прежде всего, механизмы wait
и notify
не такие уж смешные. Это самый элементарный способ координации двух или более потоков в Java. Важно понимать, что здесь происходит:
Тема 1:
synchronized (someLock) {
System.out.println("Thread 1 going to wait ...");
someLock.wait();
System.out.println("Threads 1 got notified.");
}
Тема 2:
synchronized (someLock) {
System.out.println("Notifying");
someLock.notify();
System.out.println("Exiting block.");
}
Вызов wait()
снимет блокировку, позволяя другому потоку завладеть ею. На этом этапе поток 1 не сможет продолжить , даже если он получит уведомление . Эта документация ясно заявляет это:
Пробужденная нить не сможет продолжаться до текущего
поток снимает блокировку этого объекта.
Таким образом, только после того, как поток 2 выйдет из блока synchronized
, поток 1 продолжит работу с кодом после wait()
.
Thread.join()
- синтаксический сахар, вспомогательный метод, который под капотом использует те же самые wait
и notify
/ notifyAll()
. На самом деле javadoc предостерегает от использования wait
и notify
на Thread
объектах, чтобы не мешать этому механизму.
Эта реализация использует цикл вызовов this.wait, обусловленных
this.isAlive. Поскольку поток завершает, метод this.notifyAll
вызывается. Рекомендуется, чтобы приложения не использовали ожидание, уведомление или
notifyAll on экземпляров Thread.
Thread.sleep()
не имеет отношения к wait
и notify
. Он не нуждается в блокировке объекта и не должен находиться в блоке synchronized
.
Ваш код, кажется, синхронизируется с объектом с именем joinLock
, в то время как outputThread.join()
будет синхронизироваться и ожидать объекта outputThread
. Они не связаны. Во всяком случае, вы можете рисковать блокировкой, если outputThread
синхронизируется с joinLock
. Без кода для outputThread
я не могу сказать.