2017-01-29 2 views
2

СценарийДолжен ли я использовать ThreadLocal в этом многопоточном сценарии с высоким трафиком?

Мы разрабатываем API, который будет обрабатывать около 2-3 миллионов посещений в час в многопоточной среде. Сервер Apache Tomcat 7.0.64.

У нас есть пользовательский объект с большим количеством данных, назовем его XYZDataContext. Когда приходит новый запрос, мы связываем объект XYZDataContext с контекстом запроса. Один объект XYZDataContext для каждого запроса. Мы будем создавать разные потоки параллельно, чтобы обслуживать этот запрос для сбора/обработки данных из/в объект XYZDataContext. Наши потоки, которые будут обрабатывать вещи параллельно, нуждаются в доступе к этому объекту XYZDataContext и , чтобы избежать прохождения вокруг этого объекта во всем приложении, к различным объектам/методам/потокам, мы думаем сделать его threadlocal. Темы будут использовать данные из объекта XYZDataContext, а также будут обновлять данные в этом объекте. Когда поток заканчивается, мы планируем объединить данные из обновленного объекта XYZDataContext в порожденном дочернем потоке в объект XYZDataContext основного потока.

Мои вопросы:

  1. Является ли это хороший подход?

  2. Связанные с потоком риски - сервер Tomcat будет поддерживать threadpool, и я прочитал, что использование threadlocal с пулами потоков - это катастрофа, потому что поток не GCed за отзыв и повторно используется, поэтому ссылки на объекты threadlocal не получат GCed и будут в хранении огромных объектов в памяти, которые нам больше не нужны, в конечном итоге в результате возникают проблемы с OutOfMemory ...

    ОСТАВШИМСЯ, что на них ссылаются как слабые ссылки, чтобы сразу получить GCed.
    Мы используем Java 1.7 open JDK. Я видел исходный код для ThreadLocal, и хотя ThreadLocalMap.Entry является слабым отношением, он не связан с ReferenceQueue, а комментарий для конструктора Entry говорит «, поскольку очереди ссылок не используются, занесенные записи гарантированно будут удалены только при запуске таблицы «

    Я думаю, что это отлично работает в случае с кешами, но это не самое лучшее в нашем случае. Я хотел бы, чтобы объект threadlocal XYZDataContext был немедленно скомпонован. Будет ли эффективен метод ThreadLocal.remove()? Есть ли способ принудительно освободить пространство в следующем запуске GC?

  3. Это правильный сценарий использования объектов ThreadLocal? Или мы злоупотребляем понятием threadlocal и используем его там, где его не следует использовать?

+0

Все в порядке. Не беспокойтесь о GC, если вы сразу же удалите(). – ZhongYu

ответ

1

Мое чувство кишки говорит мне, что вы на неправильном пути. Поскольку у вас уже есть центральный объект контекста (один для всех потоков), и вы хотите получить к нему доступ из нескольких потоков одновременно, я бы пошел с Singleton, на котором был размещен объект контекста, и предоставил потоковые методы для доступа к нему.

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

e.г

Singleton.getInstance().adjustContext(ContextAdjuster contextAdjuster) 

Вы также можете рассмотреть возможность использования THREADSAFE очереди, заполняя его с ContextAdjuster объектов из ваших потоков и, наконец, ее обработку в потоке данного контекста.

Google для таких вещей, как параллельная, блокирующая и неблокирующая очередь на Java. Я уверен, что вы найдете тонны кода примера.

+0

Это интересное предложение (threadafe queue + contextAdjuster). Подумайте об этом. Кроме того, я немного обновил этот вопрос, чтобы дать более подробную информацию - XYZDataContext будет инициализирован при поступлении нового запроса и будет находиться в контексте запроса. И спросил, может ли ThreadLocal.remove() иметь какое-либо значение? - просто FYI. Спасибо. –

+0

Не уверен, если я правильно вас пойму. у вас есть только один объект контекста, правильно? Соединение между Контекстом и Контекст-Настройщиком может быть выполнено как шаблон посетителя. –

+0

Один объект XYZDataContext для каждого запроса. Мы будем создавать разные потоки параллельно, чтобы обслуживать этот запрос для сбора/обработки данных из/в объект XYZDataContext. Надеюсь, я ответил на ваши сомнения. –

Смежные вопросы