Когда и как я должен использовать переменную ThreadLocal?

Пришел на эту старую нить и подумал, что я попробую свою руку при выполнении быстрой функции. Я полагаюсь на упорядочение переменных параметра ORs, разделенных каналами, когда они совпадают в функции replace (), вызывает вызов. Моя цель состояла в том, чтобы использовать стандартную функцию regex-реализации. Функция javascript replace () использует как можно больше, так что тяжелая обработка может происходить в низкоуровневом обозреваемом браузером пространстве, а не в дорогих сопоставлениях javascript char-by-char .

Это совсем не научный, но мой старый Android-телефон Huawei IDEOS вялый, когда я подключаю другие функции в этом потоке к моему автозаполнению, а эта функция застегивается вдоль:

function accentFold(inStr) {
  return inStr.replace(
    /([àáâãäå])|([ç])|([èéêë])|([ìíîï])|([ñ])|([òóôõöø])|([ß])|([ùúûü])|([ÿ])|([æ])/g, 
    function (str, a, c, e, i, n, o, s, u, y, ae) {
      if (a) return 'a';
      if (c) return 'c';
      if (e) return 'e';
      if (i) return 'i';
      if (n) return 'n';
      if (o) return 'o';
      if (s) return 's';
      if (u) return 'u';
      if (y) return 'y';
      if (ae) return 'ae';
    }
  );
}

Если вы jQuery dev, вот удобный пример использования этой функции; вы можете использовать: icontains так же, как вы бы использовали: содержит в селекторе:

jQuery.expr[':'].icontains = function (obj, index, meta, stack) {
  return accentFold(
    (obj.textContent || obj.innerText || jQuery(obj).text() || '').toLowerCase()
  )
    .indexOf(accentFold(meta[3].toLowerCase())
  ) >= 0;
};
833
задан Hearen 9 May 2019 в 01:34
поделиться

7 ответов

Одно из возможных (и распространенных) применений - когда у вас есть какой-то объект, который не является потокобезопасным, но вы хотите избежать синхронизации доступа к этому объекту (я глядя на тебя, SimpleDateFormat ). Вместо этого присвойте каждому потоку свой экземпляр объекта.

Например:

public class Foo
{
    // SimpleDateFormat is not thread-safe, so give one to each thread
    private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat("yyyyMMdd HHmm");
        }
    };

    public String formatIt(Date date)
    {
        return formatter.get().format(date);
    }
}

Документация .

845
ответ дан 22 November 2019 в 21:11
поделиться

Many frameworks use ThreadLocals to maintain some context related to the current thread. For example when the current transaction is stored in a ThreadLocal, you don't need to pass it as a parameter through every method call, in case someone down the stack needs access to it. Web applications might store information about the current request and session in a ThreadLocal, so that the application has easy access to them. With Guice you can use ThreadLocals when implementing custom scopes for the injected objects (Guice's default servlet scopes most probably use them as well).

ThreadLocals are one sort of global variables (although slightly less evil because they are restricted to one thread), so you should be careful when using them to avoid unwanted side-effects and memory leaks. Design your APIs so that the ThreadLocal values will always be automatically cleared when they are not needed anymore and that incorrect use of the API won't be possible (for example like this). ThreadLocals can be used to make the code cleaner, and in some rare cases they are the only way to make something work (my current project had two such cases; they are documented here under "Static Fields and Global Variables").

150
ответ дан 22 November 2019 в 21:11
поделиться

Essentially, when you need a variable's value to depend on the current thread and it isn't convenient for you to attach the value to the thread in some other way (for example, subclassing thread).

A typical case is where some other framework has created the thread that your code is running in, e.g. a servlet container, or where it just makes more sense to use ThreadLocal because your variable is then "in its logical place" (rather than a variable hanging from a Thread subclass or in some other hash map).

On my web site, I have some further discussion and examples of when to use ThreadLocal that may also be of interest.

Some people advocate using ThreadLocal as a way to attach a "thread ID" to each thread in certain concurrent algorithms where you need a thread number (see e.g. Herlihy & Shavit). In such cases, check that you're really getting a benefit!

15
ответ дан 22 November 2019 в 21:11
поделиться

In Java, if you have a datum that can vary per-thread, your choices are to pass that datum around to every method that needs (or may need) it, or to associate the datum with the thread. Passing the datum around everywhere may be workable if all your methods already need to pass around a common "context" variable.

If that's not the case, you may not want to clutter up your method signatures with an additional parameter. In a non-threaded world, you could solve the problem with the Java equivalent of a global variable. In a threaded word, the equivalent of a global variable is a thread-local variable.

47
ответ дан 22 November 2019 в 21:11
поделиться

В документации очень хорошо сказано: «каждый поток обращается к [локальной переменной потока] (через метод get или set) имеет собственную, независимо инициализированную копию переменной ".

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

9
ответ дан 22 November 2019 в 21:11
поделиться

Как уже упоминалось @unknown (google), он используется для определения глобальной переменной, в которой указанное значение может быть уникальным в каждом потоке. Обычно его использование влечет за собой хранение некоторой контекстной информации, связанной с текущим потоком выполнения.

Мы используем его в среде Java EE для передачи идентификатора пользователя классам, которые не поддерживают Java EE (не имеют доступа к HttpSession или EJB SessionContext). Таким образом, код, который использует идентификатор для операций на основе безопасности, может получить доступ к идентификатору из любого места, без необходимости явно передавать его при каждом вызове метода.

Цикл операций запрос / ответ в большинстве вызовов Java EE делает это легко использовать, поскольку он дает четко определенные точки входа и выхода для установки и сброса ThreadLocal.

3
ответ дан 22 November 2019 в 21:11
поделиться

Поскольку ThreadLocal является ссылкой на данные в данном потоке , вы можете получить утечку при загрузке классов при использовании ThreadLocal на серверах приложений, использующих пулы потоков. Вы должны быть очень осторожны при очистке любых ThreadLocal s, которые вы получаете () или set () , используя ThreadLocal метод remove () .

Если вы не выполните очистку, когда закончите, любые ссылки, которые он содержит на классы, загруженные как часть развернутого веб-приложения, останутся в постоянной куче и никогда не будут собирать мусор. Повторное развертывание / удаление веб-приложения не очистит ссылку каждого потока на класс (ы) вашего веб-приложения, поскольку поток не является чем-то, принадлежащим вашему веб-приложению. Каждое последующее развертывание будет создавать новый экземпляр класса, который никогда не будет собирать мусор.

В результате вы получите исключения из нехватки памяти из-за java.lang.OutOfMemoryError: пространства PermGen и после некоторого поиска в Google. вероятно, просто увеличит -XX: MaxPermSize вместо исправления ошибки.

Если вы столкнетесь с этими проблемами, вы можете определить, какой поток и класс сохраняют эти ссылки, используя Eclipse '

414
ответ дан 22 November 2019 в 21:11
поделиться