В моей программе я создаю несколько потоков в основном () метод. Последняя строка в основном методе является вызовом к System.out.println (), который я не хочу называть, пока все потоки не умерли. Я попытался назвать Thread.join () на каждом потоке однако, который блокируют каждый поток так, чтобы они выполнились последовательно вместо параллельно.
Существует ли способ заблокировать основное () поток, пока все другие потоки не закончили выполняться? Вот соответствующая часть моего кода:
public static void main(String[] args) {
//some other initialization code
//Make array of Thread objects
Thread[] racecars = new Thread[numberOfRaceCars];
//Fill array with RaceCar objects
for(int i=0; i<numberOfRaceCars; i++) {
racecars[i] = new RaceCar(laps, args[i]);
}
//Call start() on each Thread
for(int i=0; i<numberOfRaceCars; i++) {
racecars[i].start();
try {
racecars[i].join(); //This is where I tried to using join()
//It just blocks all other threads until the current
//thread finishes.
} catch(InterruptedException e) {
e.printStackTrace();
}
}
//This is the line I want to execute after all other Threads have finished
System.out.println("It's Over!");
}
Спасибо за парней справки!
Eric
Вы запускаете свои потоки и сразу же ждете их завершения (используя join()
). Вместо этого следует выполнить join()
вне цикла for в другом цикле for, например:
// start all threads
for(int i=0; i<numberOfRaceCars; i++) {
racecars[i].start();
}
// threads run... we could yield explicity to allow the other threads to execute
// before we move on, all threads have to finish
for(int i=0; i<numberOfRaceCars; i++) {
racecars[i].join(); // TODO Exception handling
}
// now we can print
System.out.println("It's over!");
Вы можете использовать метод соединения. См. Документацию здесь
Вы можете wait()
в вашем главном потоке и заставить все потоки выдать notifyAll()
, когда они закончат. Тогда каждый раз, когда ваш главный поток будет пробуждаться таким образом, он сможет проверить, жив ли еще хотя бы один поток, и тогда вы wait()
еще немного.
Вы можете добавить хук выключения для сообщения "Its Over". Таким образом, оно будет выдаваться при завершении программы, и вам не придется ждать каждый поток.
Можно сделать так, чтобы последняя строка находилась в потоке "мониторинга". Он будет проверять время от времени, что он единственный запущенный поток и состояние завершения == true
, и затем может сработать, если это так. Тогда он мог бы делать другие вещи, кроме println
Вы можете разделить объект CyclicBarrier
между вашими RaceCar
ами и главным потоком, и заставить потоки RaceCar
вызывать await()
, как только они выполнят свою задачу. Постройте барьер с количеством потоков RaceCar
плюс один (для главного потока). Главный поток продолжит работу, когда все RaceCar
ы закончат работу.
См. http://java.sun.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html
Подробнее, постройте CyclicBarrier
в главном потоке и добавьте барьер. await()
в класс RaceCar
непосредственно перед выходом метода run()
, а также добавьте вызов barrier.await()
перед вызовом System.out.println()
в главном потоке.