Обобщения с многопоточностью и совместным использованием экземпляров - PullRequest
0 голосов
/ 24 января 2019

У меня есть общий класс, который можно набросать вот так

public class Shared<T extends EntityBase> {

    private HashMap<String, Class<? extends Executor<T>>> classes;
    private HashMap<String, ? super Executor<T>> instances;
    private List<Entity> entities;
    private Compiler compiler;

   // Constructor and getters

    public void put(Entity entity, Source source) {
        Class<?> cls = compiler.load(source);
        put(entity, (Class<? extends Executor<T>>) cls );

    }

    private void put(Entity entity, Class<? extends Executor<T>> cls) throws IllegalAccessException, InstantiationException {
        classes.put(entity.getId(), cls);
        instances.put(entity.getId(), cls.newInstance());
        entities.add(entity);
    }
}

В моем приложении этот класс создается один раз , и несколько независимых потоков обращаются к нему.

В частности, один поток отвечает за запись в него, а несколько обращаются к его экземплярам Map через геттер.

Когда я получаю экземпляр Source и вызываю метод private put, карты и список обновляются.

В сеансе отладки с InteliiJ при выходе из фрейма класса Singleton этот класс теряет свое состояние, и Map и List снова становятся пустыми.

Как я могу это объяснить? Почему экземпляры Class<? extends Executor<T>> и ? super Executor<T> потеряны?

1 Ответ

0 голосов
/ 24 января 2019

дженерики фактически являются лишь частью воображения компилятора;во время выполнения этого все прошло.Таким образом, универсальные шаблоны в этом примере не имеют абсолютно никакого отношения к тому, что вы наблюдаете.

Вставленный код не может создать эффект, который вы видите (когда карта сначала изменяется, а затем возвращается).Но в целом, если вы вызываете 'put' из разных потоков, этот код нарушается.Там нет охранников для предотвращения синхронного доступа.Когда вы обновляете карту одновременно из разных потоков, спецификация карты специально говорит, что все может произойти (В этом смысле карта, просто сбрасывающая на пустое, технически «соответствует спецификации», в том смысле, что все разрешено, потому что вы не выполняете многопоточностьпроблема правильная).

Простое решение - пометить второй метод пут как "синхронизированный".

Альтернативная стратегия - использовать списки и карты из пакета java.util.concurrent.Тем не менее, никакое использование не позволит вам синхронизировать classes, instances и entities синхронно друг с другом.Только synchronized может сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...