Я создаю приложение Java с потоком логики приложения и потоком доступа к базе данных. Оба они сохраняются в течение всего срока службы приложения, и оба должны работать одновременно (один разговаривает с сервером, другой разговаривает с пользователем; когда приложение полностью запущено, мне нужно оба работали).
Однако при запуске мне нужно убедиться, что изначально поток приложения ждет, пока поток db не будет готов (в настоящее время определяется путем опроса настраиваемого метода dbthread.isReady()
). Я бы не возражал, если поток приложения блокируется до тех пор, пока поток db не будет готов.
Thread.join()
не похоже на решение - поток db завершается только при завершении работы приложения.
while (!dbthread.isReady()) {}
вроде работает, но пустой цикл потребляет много циклов процессора.
Есть другие идеи? Спасибо.
источник
a
ожидает объекта,synchronised(object)
как может другой потокsynchronized(object)
выполнить вызовobject.notifyAll()
? В моей программе все просто застряло наsynchronozed
блоках.object.wait()
эффективную разблокировку блокировки этого объекта. Когда второй поток «выходит» из своего синхронизированного блока, другие объекты освобождаются изwait
метода и повторно получают блокировку в этой точке.Используйте CountDownLatch со счетчиком 1.
Теперь в ветке приложения:
В потоке db после того, как вы закончите, сделайте -
источник
countDown()
вfinally{}
блокТребование:
Ответ ::
Работа выполнена!! См. Пример ниже
Вывод этой программы:
Вы можете видеть, что до завершения задачи требуется 6 секунд, что больше, чем у другого потока. Итак, Future.get () ждет, пока задача не будет выполнена.
Если вы не используете future.get (), он не дожидается завершения и выполняет в зависимости от потребления времени.
Удачи с параллелизмом Java.
источник
CountdownLatch
es, но ваш подход гораздо более гибкий.Множество правильных ответов, но без простого примера. Вот простой и простой способ использования
CountDownLatch
:источник
Тогда используйте этот класс следующим образом:
Создайте ThreadEvent:
В методе ждем результатов:
И в методе, который создает результаты после того, как были созданы все результаты:
РЕДАКТИРОВАТЬ:
(Извините за редактирование этого сообщения, но у этого кода очень плохое состояние гонки, и у меня недостаточно репутации, чтобы комментировать)
Вы можете использовать это только если вы на 100% уверены, что signal () вызывается после await (). Это одна из основных причин, по которой вы не можете использовать объект Java, например, Windows Events.
Если код выполняется в таком порядке:
тогда поток 2 будет ждать вечно . Это потому, что Object.notify () пробуждает только один из запущенных в данный момент потоков. Поток, ожидающий позже, не пробуждается. Это сильно отличается от того, как я ожидаю, что события будут работать, когда событие сигнализируется до тех пор, пока а) не будет выполнено ожидание или б) явно не сброшено.
Примечание. В большинстве случаев вам следует использовать notifyAll (), но это не имеет отношения к описанной выше проблеме «ждать вечно».
источник
Попробуйте исключить класс CountDownLatch из
java.util.concurrent
пакета, который обеспечивает механизмы синхронизации более высокого уровня, которые гораздо менее подвержены ошибкам, чем любой другой материал низкого уровня.источник
Вы можете сделать это, используя объект Exchanger, совместно используемый двумя потоками:
И во второй ветке:
Как говорили другие, не принимайте этот беззаботный и просто скопируйте код. Сначала почитайте.
источник
Интерфейс будущего от
java.lang.concurrent
пакета предназначен для обеспечения доступа к результатам, вычисленным в другом потоке.Взгляните на FutureTask и ExecutorService, чтобы найти готовый способ делать такие вещи.
Я настоятельно рекомендую прочитать Java Concurrency In Practice всем, кто интересуется параллелизмом и многопоточностью. Очевидно, что он сконцентрирован на Java, но есть много мяса и для тех, кто работает с другими языками.
источник
Если вам нужно что-то быстрое и грязное, вы можете просто добавить вызов Thread.sleep () в свой цикл while. Если вы не можете изменить библиотеку базы данных, то другого простого решения действительно нет. Опрос базы данных до готовности с периодом ожидания не убьет производительность.
Вряд ли что-то, что можно назвать элегантным кодом, но выполняет свою работу.
Если вы можете изменить код базы данных, то лучше использовать мьютекс, предложенный в других ответах.
источник
Это относится ко всем языкам:
Вы хотите иметь модель событие / слушатель. Вы создаете слушателя для ожидания определенного события. Событие будет создано (или сигнализировано) в вашем рабочем потоке. Это будет блокировать поток до тех пор, пока не будет получен сигнал, вместо постоянного опроса, чтобы увидеть, выполняется ли условие, например, решение, которое у вас есть в настоящее время.
Ваша ситуация является одной из наиболее распространенных причин взаимоблокировок - убедитесь, что вы сигнализируете другому потоку, независимо от ошибок, которые могли возникнуть. Пример - если ваше приложение выдает исключение и никогда не вызывает метод, чтобы сигнализировать другому, что все было завершено. Это сделает так, чтобы другой поток никогда не «просыпался».
Я предлагаю вам изучить концепции использования событий и обработчиков событий, чтобы лучше понять эту парадигму, прежде чем реализовывать свое дело.
В качестве альтернативы вы можете использовать вызов функции блокировки с помощью мьютекса, что заставит поток ждать, пока ресурс освободится. Для этого вам нужна хорошая синхронизация потоков, например:
источник
Вы можете читать из блокирующей очереди в одном потоке и писать в нее в другом потоке.
источник
поскольку
join()
был исключенВы можете рассмотреть другие альтернативы:
invokeAll из
ExecutorService
ForkJoinPool или newWorkStealingPool из
Executors
(начиная с версии Java 8)источник
Эту идею можно применить ?. Если вы используете CountdownLatches или Semaphores, отлично работает, но если вы ищете самый простой ответ для интервью, я думаю, что это применимо.
источник