Проблема, которую вы описываете, звучит так, как если бы вы могли извлечь выгоду из примитивов синхронизации Java, таких как Object.wait
и Object.notify
.
Поток, которому принадлежит блокировка / монитор данного объекта (например, с помощью ключевого слова synchronized
), может вызвать wait
вместо того, чтобы зацикливаться и спать в шаблоне занятости / ожидания, как в while(!Thread.interrupted())
, который может тратить много циклов ЦП.
Как только поток переходит в состояние ожидания, он снимает блокировку, которую он удерживает, что позволяет другому потоку получить такую же блокировку и, возможно, изменить какое-то состояние, а затем уведомить один или несколько ожидающих потоков через notify / notifyAll.
Обратите внимание, что необходимо соблюдать осторожность, чтобы обеспечить получение и снятие блокировок в одном и том же порядке, чтобы избежать сценариев тупиковой ситуации, когда задействовано более одной блокировки. Также попробуйте использовать тайм-ауты во время ожидания, чтобы убедиться, что ваш поток не будет ждать неопределенно долго условия, которое может никогда не возникнуть. Если при вызове notify много ожидающих потоков, имейте в виду, что вы можете не знать, какой поток будет запланирован, но вы можете установить политику справедливости, чтобы помочь повлиять на это.
В зависимости от структуры вашего кода вы можете избежать некоторых примитивов более низкого уровня, таких как синхронизированные блоки, используя некоторые API более высокого уровня, такие как https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html
или ключевые слова, такие как volatile
, для переменных, которые содержат общее изменяемое состояние ( как условие, которое вы хотите дождаться, чтобы убедиться, что результат записи наблюдается при последующем чтении в отношении «происходит до».