Гонки инициализации с отказобезопасности


У меня такой usecase, у меня есть многопоточные среды, и я хочу, чтобы инициализировать некоторые параметры только только. Дело в том, что когда я инициализировать параметры я называю функцию, которая иногда выходит из строя и потребуется некоторое время, на такой случай я хочу, чтобы следующий поток для повторной инициализации. Реализация может выглядеть примерно так:

private static boolean action(int i){
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    double randomVal = Math.random();
    System.out.println(String.format("%d: random val is %s", i, randomVal));
    if(randomVal < 0.8) return false;
    //SET STATIC VARIABLES
    return true;
}

Для того, чтобы справиться с проблемой, я придумал следующую идею, у меня есть AtomicBoolean что мне подсказывает ли параметры были инициализированы или нет и я запустить код инициализации в synchronized блок. Внутри каждого блока synchronized, я перепроверяю, логическое, чтобы увидеть, если поток не будет инициализировать переменные, в то время как я ждал.

private static AtomicBoolean initialized = new AtomicBoolean(false);

public static void main(String[] args) {
    ExecutorService executors = Executors.newFixedThreadPool(15);

    IntStream.range(0,15).forEach(i -> {
        executors.submit(() -> {
            if(!initialized.get()){
                synchronized (Concurrncy.class){
                    if(!initialized.get()){
                        if(action(i)) initialized.set(true);
                    }
                }
            }
        });
    });

    executors.shutdown();
}

Кажется, немного перепроверить дважды логическое. Для всех учитель Java прокомментируйте, пожалуйста, код (также пример кода) и скажите, что можно сделать лучше



103
1
задан 5 февраля 2018 в 05:02 Источник Поделиться
Комментарии