В рекомендации ментора написано как решить, но что тут происходит мне решительно непонятно!
Я насчитал 3 нити:
1. Нить RethrowableTask
2. Нить A, задается в мэйне, запускается внутри RethrowableTask после его запуска.
3. Нить Executor которая закрывает нить RethrowableTask.
Программа по моему работает так:
1. создается объект RethrowableTask
2. создается первая нить на основе созданного объекта.
3. первая нить запускает вторую.
4. вторая нить инициализирует переменную throwable
5. какая-то непонятная фигня, назовем ее магией.
6. ждем секунду.
7. магия создает третью нить которая закрывает первую
8. проверяем инициализацию переменной throwable
Вот я не понимаю почему я должен поставить volatile там где просит ментор, когда из трех нитей только одна имеет дело с этой переменной, при этом она ее инициализирует, а не читает???
package com.javarush.task.task26.task2605;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/*
Трудолюбие - душа всякого дела и залог благосостояния
*/
public class Solution {
private static ScheduledExecutorService interruptScheduledExecutor;
private static Thread taskThread;
private static RethrowableTask task;
public static void main(String[] args) throws Exception {
runTaskBySchedule(new Runnable() {
@Override
public void run() {
System.out.println("A");
throw new RuntimeException("it's test");
}
}, 1_000, TimeUnit.MILLISECONDS
);
interruptScheduledExecutor.shutdown();
}
public static void runTaskBySchedule(final Runnable runnable, long timeout, TimeUnit unit) throws Exception {
task = new RethrowableTask(runnable);
taskThread = new Thread(task);
taskThread.start();
interruptScheduledExecutor = Executors.newScheduledThreadPool(3);
interruptScheduledExecutor.schedule(new Runnable() {
public void run() {
System.out.println("Executor starting");
taskThread.interrupt();
System.out.println("RethrowableTask is interrupt");
}
}, timeout, unit);
Thread.sleep(unit.toMillis(timeout));
try {
task.rethrow();
} catch (Throwable throwable) {
System.out.println(throwable.getMessage());
}
}
public static class RethrowableTask implements Runnable {
private Throwable throwable;
private Runnable runnable;
public RethrowableTask(Runnable runnable) {
this.runnable = runnable;
}
public void run() {
try {
System.out.println("RethrowableTask start");
runnable.run();
} catch (Throwable throwable) {
System.out.println("catching throwable");
this.throwable = throwable;
}
}
public void rethrow() throws Exception {
if (throwable != null) {
System.out.println("B");
throw new Exception(throwable);
}
}
}
}