Как инициализировать ThreadLocal<List <Object >>

Ниже приведен мой код, в котором я объявляю ThreadLocal переменная:

public static final ThreadLocal<List<Object>> ARGS = new ThreadLocal<>(); 

Я использую эту переменную в следующем фрагменте:

private static void getParams(Token... tokens) {
    if(ARGS == null) {
        new LinkedList<>();
    }
    if(tokens.length > 2) {
        for(Token token : Arrays.copyOfRange(tokens, 2, tokens.length)) {
            ARGS.get().add(ArgHelper.resolveArg(token));
        }
    }
}

Нижняя строка:

ARGS.get().add(ArgHelper.resolveArg(token)); 

дает мне NullPointerException ты получаешь ценность от ArgHelper.resolveArg(token),

3 ответа

Java 8

private static final ThreadLocal<List<Object>> list = 
    ThreadLocal.withInitial(ArrayList::new);

Заметить, что:

if(ARGS == null) {
  new LinkedList<>();
}

ничего не делает ARGS создается как final ненулевое значение, поэтому этот блок никогда не будет введен. Даже если бы это сделал, позвонив new LinkedList<>(); в одиночку просто строит LinkedList экземпляр, который немедленно выпадает из области видимости и является сборщиком мусора. Ничто не может ссылаться на это.

Чтобы правильно инициализировать ThreadLocal Посмотрите документацию, в которой приведен пример, показывающий, как установить начальное значение (путем переопределения метко названного initialValue() метод).

Вы можете сделать что-то подобное:

public static final ThreadLocal<List<Object>> ARGS = new ThreadLocal<List<Object>>() {
  @Override protected List<Object> initialValue() {
    return new LinkedList<>();
  }
};

Тем не менее, некоторые указатели:

  • Вы должны предпочесть ArrayList над LinkedList почти во всех случаях.
  • Делать ARGSprivate если это абсолютно необходимо. Обычно лучше минимизировать видимость ThreadLocal экземпляры, например, ограничивая его классом, содержащим класс, и предоставляя более приятный API пользователям этого класса.
  • Рассмотрим более значимый тип, чем List<Object> - вы заставляете всех пользователей проверять и выводить содержимое списка, если оно может содержать какие-либо Object,

Это не то, как вы используете ThreadLocal,

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

if(ARGS.get() == null) {
    ARGS.set(new LinkedList<>());
}

Конечно, я бы посоветовал не использовать ThreadLocal вообще, особенно если у вас нет опыта его использования.

Другие вопросы по тегам