Я не уверен, каково именно ваше ожидаемое поведение, потому что я не смог получить правильный пример из вашего кода, чтобы выяснить, что он делает, и угадать, что он должен делать.
Однако: если Если вы хотите запускать дочерние задачи параллельно, вам может помочь следующий фрагмент:
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreaderApplication {
private static final int THREADS_COUNT = 3;
private static final int DELAY_OF_FIRST_TASK_FROM_START = 3;
private static final int DELAY_OF_SECOND_TASK_FROM_START = 5;
private static final int DELAY_OF_THIRD_TASK_FROM_START = 7;
private static final int DELAY_OF_FOURTH_TASK_FROM_START = 9;
private static final int DELAY_OF_FIFTH_TASK_FROM_START = 11;
private static final int DELAY_OF_SIXTH_TASK_FROM_START = 14;
public static void main(final String[] args) {
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(THREADS_COUNT);
final Runnable task0 = new RunnableTask("Demo Task 1");
final Runnable task1 = new RunnableTask("Demo Task 2");
final Runnable task2 = new RunnableTask("Demo Task 3");
final Runnable task3 = new RunnableTask("Demo Task 4");
final Runnable task4 = new RunnableTask("Demo Task 5");
final Runnable task5 = new RunnableTask("Demo Task 6");
System.out.println("Planning tasks; time: " + new Date());
executor.schedule(task0, DELAY_OF_FIRST_TASK_FROM_START, TimeUnit.SECONDS);
executor.schedule(task1, DELAY_OF_SECOND_TASK_FROM_START, TimeUnit.SECONDS);
executor.schedule(task2, DELAY_OF_THIRD_TASK_FROM_START, TimeUnit.SECONDS);
executor.schedule(task3, DELAY_OF_FOURTH_TASK_FROM_START, TimeUnit.SECONDS);
executor.schedule(task4, DELAY_OF_FIFTH_TASK_FROM_START, TimeUnit.SECONDS);
executor.schedule(task5, DELAY_OF_SIXTH_TASK_FROM_START, TimeUnit.SECONDS);
System.out.println("Awaiting tasks; time: " + new Date());
executor.shutdown();
// use executor.awaitTermination(amountOfSeconds, TimeUnit.SECONDS) if you want to wait a definite amount of time instead of shutting down upon last daemon-thread completes
System.out.println("Main program ready to exit; time: " + new Date());
}
private static class RunnableTask implements Runnable {
private final String text;
public RunnableTask(final String text) {
this.text = text;
}
@Override
public void run() {
System.out.println(text);
}
}
}
Примечания В этом состоянии основная программа выполняется почти сразу. executor.shutdown()
заставляет пул больше не принимать новые Callables, но не немедленно отключает все. Вместо этого он ожидает окончания последнего потока демона.
В качестве альтернативы вы можете подождать некоторое время, используя executor.awaitTermination(amountOfSeconds, TimeUnit.SECONDS)
. В этом случае основной поток будет ожидать завершения в течение заданного промежутка времени, прежде чем приступить к его завершению.
В этом примере, если вы используете, например, int amountOfSeconds = 5
, ваш основной поток будет ждать на executor.awaitTermination(amountOfSeconds, TimeUnit.SECONDS)
в течение 5 секунд до окончания его исполнения. Тем не менее: даже если основной поток уже завершил выполнение, daemon- / child-threads этого не сделали. Поэтому перед завершением работы основного приложения выполняемые задачи RunnableTask
завершаются.
Редактировать Этот код протестирован, но в нем есть много возможностей для улучшения ради гибкости. Судя по приведенному выше коду, вы должны больше разделять классы и методы (например, по интересам), и в моем примере можно утверждать, что, например, использование правильного регистратора (такого как Log4J2 или Slf4J) было бы хорошей идеей. Я упустил многое, чтобы дать гораздо более лаконичное решение.
Я также предлагаю не изобретать велосипед, если только по какой-то причине это не нужно делать. Используйте существующие подходы к созданию пула потоков (на самом деле их несколько, я только что показал один из них).