Два класса не делают одно и то же.Вы, вероятно, можете найти решение самостоятельно, сравнив их.Во-первых, вы точно знаете, как работает ваш первый класс (марафон)?В частности, что, по вашему мнению, делает следующая строка?
t1.join(100);
Поток t1, который только что начал работать, только что вошел в цикл, который считает один раз каждые 200 миллисекунд.Вызов join (100) просто заставляет текущий (основной) поток ждать 100 миллисекунд.Вы добьетесь точно таких же результатов, заменив эту строку на следующую:
Thread.sleep (100);
Теперь, когда основной поток спал в течение 100 миллисекунд, он запускает поток t2.Теперь два потока работают параллельно, и каждые 200 миллисекунд оба потока выводят строку, второй поток задерживается на 100 миллисекунд, чтобы они выглядели равномерно с чередованием.
Теперь давайте рассмотрим ваш второй метод, Marathon2.Несколько отличий от первого класса сразу очевидны:
- Сон в Runnable вне цикла, а не внутри.
- Сон вRunnable составляет всего 100 миллисекунд вместо 200.
- Максимальное время ожидания в главном потоке составляет 500 миллисекунд вместо 100.
- Метод Future.get вызывает исключение TimeoutException вместо просто продолжения.В любом случае мы можем просто заменить этот вызов на сон, поскольку это все, что делает первый класс.
Итак, сгладив различия, мы получаем следующий класс Marathon2, который ведет себя аналогичнодругой класс (марафон), с чередованием потоков:
public class Marathon2 {
public static void main(String[] args)
throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService service = null;
Runnable task = () -> {
try {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()
+ " is running... " + i);
TimeUnit.MILLISECONDS.sleep(200);
}
} catch (InterruptedException e) {
}
};
try {
service = Executors.newFixedThreadPool(4);
Future<?> job1 = service.submit(task);
TimeUnit.MILLISECONDS.sleep(100);
Future<?> job2 = service.submit(task);
} finally {
if (service != null)
service.shutdown();
}
}
}