Ожидая окончания других потоков, мы можем использовать либо join
, либо CountdownLatch
. Каковы преимущества и недостатки использования любого из этих двух механизмов?
В чем разница между join и CountDownLatch?
Ответ 1
Вы можете использовать только Thread.join
, если вы сами обрабатываете потоки. Большинство людей предпочитают не обращаться к мелочам обработки потоков напрямую, а вместо этого использовать ExecutorService
для их обработки. ExecutorService
прямо не показывают, как они выполняют задачи, поэтому вам придется использовать CountDownLatch
: (Предполагая, что вы не хотите просто shutdown
всю службу, то есть.)
ExecutorService service = Executors.newFixedThreadPool(5);
final CountDownLatch latch = new CountDownLatch(5);
for(int x = 0; x < 5; x++) {
service.submit(new Runnable() {
public void run() {
// do something
latch.countDown();
}
});
}
latch.await();
Ответ 2
CountdownLatch ориентирован на задачи - он нить-агностик. Целая куча несвязанных наборов задач может быть отправлена в threadPool, а CountdownLatch гарантирует, что каждый набор уведомляет создателя о завершении. Join() - это раздражающее аберрация, которая связывает задачи с потоками и, просто говоря, никогда не должна вводить язык в первую очередь. К сожалению, в большой, дымящейся куче учебников по потокам упоминается Join() на первой странице, тем самым вводя потоки новичкам в качестве тупикового генератора и генерируя thread-funk: (
Ответ 3
Другое отличие после join()
, поток можно разблокировать только тогда, когда объединенный поток завершил свое выполнение, а в CountDownLatch
поток может уменьшить счетчик в любое время либо при завершении потока, либо между ними на основе любого условия.
Таким образом, мы можем лучше контролировать разблокировку потока, а не только в зависимости от завершения объединенного потока.
Ответ 4
CountdownLatch
позволяет вам изменить реализацию элемента, чтобы он мог быть отправлен в службу-исполнитель вместо непосредственного использования потоков.
Класс CountdownLatch
позволяет нам координировать запуск и остановку потоков. Типичные виды использования:
- Мы можем запустить несколько потоков одновременно;
- Мы можем подождать
несколько потоков для завершения (тогда как, например,
Thread.join()
метод позволяет подождать только один поток).
Вы можете посмотреть на это → http://javahowto.blogspot.com/2011/08/when-to-join-threads-with.html
Ответ 5
join() ожидает завершения другого потока, в то время как CountDownLatch предназначен для другой цели. Если вы используете CountDownLatch, вам не нужно иметь ссылку на потоки, для которых вы ждете, как мы должны делать, используя join(). Предположим, вы хотите начать игру, когда должно быть доступно как минимум 2 игрока. Вы можете использовать countdownlatch в этом случае. Но вы не можете добиться этого, просто используя соединение, потому что у вас нет другого потока (в данном случае игрока), на котором вы можете написать join().