Каков наилучший способ удалить ссылки на локальные объекты потока

У меня есть статический объект ThreadLocal в моем веб-приложении, где я инициализирую его некоторым значением по умолчанию в классе фильтра веб-сервлета перед обработкой запроса. В приложении несколько других классов (таких как процессоры) используют и обновляют его значение. Я читал в некоторых статьях, что объекты, созданные с помощью ThreadLocal, по-прежнему связаны с потоками, хотя процесс запроса завершен, поскольку потоки поддерживаются в пуле, управляемом контейнером. Это приводит к утечкам памяти, если объекты не удаляются из переменной ThreadLocal.

В связи с этим у меня два вопроса.

  1. Какой из приведенных ниже вариантов является лучшим и правильным способом удалить его ссылку, чтобы предотвратить утечку памяти.

    ThreadLocal obj;
    1) obj.remove(); // remove the contents of ThreadLocal.
    2) obj.set(""); // set some default value
    3) obj.set(null); // set null
    

person kswaughs    schedule 29.02.2016    source источник
comment
Ответ на (1) - (1), или позволить потоку выйти. Второй вопрос непонятен.   -  person user207421    schedule 29.02.2016
comment
Перефразировал мой второй вопрос?   -  person kswaughs    schedule 29.02.2016


Ответы (1)


Используйте ThreadLocal#remove(). Однако это не является вашей главной заботой. Ваша главная забота должна заключаться в том, чтобы вы могли гарантировать, что remove() также вызывается в исключительных случаях. Правильный способ сделать это — выполнить remove() в finally блока try, где создается и делегируется TLS.

YourContext context = null;
try {
    context = YourContext.create(request, response);
    chain.doFilter(request, response);
} finally {
    if (context != null) context.release(); // Invokes remove().
}

Если вы уже используете Java 7+, еще лучше позволить вашему контексту реализовать AutoCloseable, где close() вызывает remove(), а затем использует блок try-with-resources.

try (YourContext context = YourContext.create(request, response)) {
    chain.doFilter(request, response);
}

Дополнительные советы о том, как создать YourContext, см. в Получение веб-сеанса из POJO вне веб-контейнера.

person BalusC    schedule 29.02.2016
comment
Я все еще использую Java 6 и в классе Filter я инициализирую и удаляю до и после цепного вызова. Не могли бы вы также помочь мне со вторым вопросом? - person kswaughs; 29.02.2016
comment
Как ответили, удаление должно происходить в блоке finally. Что касается второго вопроса, вы должны задавать один вопрос на вопрос. Материя GC, по крайней мере, не связана с материей TLS. Если объект не имеет ссылок, он подходит для GC. Просто как тот. - person BalusC; 29.02.2016