Запуск пула потоков в контейнере сервлета - PullRequest
2 голосов
/ 26 декабря 2008

У меня есть сервлет S, который обрабатывает обратные вызовы со стороннего сайта.

Обратные вызовы происходят в определенном порядке. Таким образом, мне нужно поставить их в очередь.

Я предлагаю использовать очередь в памяти как

java.util.ConcurrentLinkedQueue

Итак, логика выглядит так:

  • Сервлет S принимает обратный вызов и помещает полученный элемент в очередь Q.
  • К этому времени поток, на котором размещен экземпляр сервлета S., завершился бы.
  • Поток-потребитель читает из Q и обрабатывает каждый из них последовательно.

Насколько я понимаю, каждый экземпляр Servlet S выполняется в своем собственном потоке.

Как мне создать единый потребительский поток для всего веб-приложения (войны), который будет обслуживать очередь? В основном мне нужны единичные экземпляры:

  1. Threadpool
  2. ConcurrentLinkedQueue

Ответы [ 5 ]

5 голосов
/ 26 декабря 2008

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

Вероятно, я бы попробовал создать DaemonServlet. Это просто обычный сервлет, который не сопоставляется с URL-адресом (за исключением, возможно, скрытого URL-адреса для целей мониторинга, хотя для такого рода вещей предпочтительнее использовать JMX). Метод init() вызывается при загрузке сервлета. Вы можете начать тему в этом. Возможно, вам может понадобиться создать два: один, который делает работу. Другой проверяет, работает ли первый, и корректно завершает его после вызова destroy().

В качестве альтернативы, если вы используете Spring (и, скажем прямо, что за хрень не использует Spring?), Вы можете просто создать бин в контексте приложения, который делает много то же самое, за исключением событий жизненного цикла Spring (например, afterPropertiesSet () в InitializingBean).

На самом деле, у меня есть еще лучшее предложение. Используйте пользователей асинхронных сообщений , которые будут намного чище и более масштабируемыми, но это основано на JMS решении, а не просто LinkedBlockingQueue (а JMS, вероятно, является В любом случае, идея получше). Однако в зависимости от ваших ограничений JMS может быть недоступен в качестве опции.

2 голосов
/ 26 декабря 2008

Помните, что пока ваши сервлеты находятся в отдельных потоках, они находятся в одном и том же экземпляре виртуальной машины, поэтому они живут в общем пространстве памяти. Если вы создадите экземпляр Singleton, он будет автоматически использоваться всеми сервлетами. Вы также можете создать отдельный сервлет, который будет выступать в качестве ваших общих данных, что дает преимущество в том, что вы можете использовать службы контейнеров, чтобы сохранять их, если хотите.

В книге OReilly по программированию сервлетов, которая доступна онлайн здесь .

, есть подробное исследование способов сделать это - технически называемое "сотрудничество сервлетов".
1 голос
/ 26 декабря 2008

О, еще одна мысль: единственное, что вы НЕ ХОТИТЕ ДЕЛАТЬ , - это пытаться управлять своими собственными пулами потоков внутри контейнера сервлета; это может сделать пул потоков намного лучше, чем вы, если вы не возитесь с ним.

0 голосов
/ 22 апреля 2019

Использование прослушивателей Я создал ThreadPool, который можно интегрировать с устаревшим приложением Tomcat, используя ServletContext для хранения ThreadPool и позволить слушателю управлять жизненным циклом, чтобы он не задерживался.

@WebListener
public class MyThreadPool implements ServletContextListener {

    private static final String CONTEXT_ATTRIBUTE = "MyThreadPool";
    private ExecutorService myThreadPool;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        myThreadPool = Executors.newFixedThreadPool(10);
        sce.getServletContext().setAttribute(CONTEXT_ATTRIBUTE, myThreadPool);
    }

    public static ExecutorService getPool(Servlet servlet) {
        return (ExecutorService) servlet.getServletConfig()
               .getServletContext().getAttribute(CONTEXT_ATTRIBUTE);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        myThreadPool.shutdown();
        sce.getServletContext().removeAttribute(CONTEXT_ATTRIBUTE);
    }
}
0 голосов
/ 26 декабря 2008

Я второй комментарий, который говорит, что управление собственным пулом потоков - плохая идея.

Сервлеты предназначены для обработки HTTP-запросов. HTTP - это протокол синхронного запроса / ответа. Логика того, как они обрабатываются, принадлежит где-то еще. Этот обработчик может быть синхронным или асинхронным, но это должно зависеть от реализации обработчика. Сервлет должен решить, какой обработчик отложить для данного ответа, и все.

Даже если вы используете Tomcat или механизм сервлета / JSP, вы все равно можете использовать Spring, JMS и MDP, добавив ActiveMQ в свою реализацию Tomcat.

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