В Java, как мне убедиться, что мое веб-приложение поддерживает потоки? - PullRequest
14 голосов
/ 10 февраля 2010

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

Ответы [ 4 ]

21 голосов
/ 10 февраля 2010

Факт: в жизни веб-приложения есть только 1 экземпляр сервлета. Он создается при запуске веб-приложения и уничтожается при завершении работы веб-приложения. Также см. этот ответ для грубой интерпретации.

Таким образом, он был разделен между всеми запросами (потоками). Если вы назначите данные области запроса или сеанса как переменную экземпляра (или, что еще хуже, как static), то это определенно не будет потокобезопасным, поскольку затем оно будет разделено между всеми запросами (потоками) от всех пользователей (сеансов) всего приложения. Вам просто нужно назначить их как локальные переменные метода, чтобы сохранить их потокобезопасность. Итак:

public class MyServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

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

Кроме того, существуют атрибуты сеанса (HttpSession), которые могут совместно использоваться несколькими запросами одного и того же пользователя, но в действительности вам не нужно беспокоиться о синхронизации доступа к сеансу. Обычно вы помещаете туда только данные пользователя, такие как вошедший в систему пользователь, предпочтения пользователя, корзину покупок и так далее. Вам просто нужно убедиться, что вы не помещаете чистые данные области запроса в область сеанса. Это будет отражено в нескольких окнах / вкладках браузера в одном сеансе.

Кроме того, существуют атрибуты приложения (ServletContext), которые являются общими для всех пользователей приложения, но обычно вы помещаете туда только константы и другие статические данные, такие как конфигурация веб-приложения, фабрика DAO, содержимое выпадающего списка, и так далее. Кстати, все это можно сделать с помощью ServletContextListener, также см. этот ответ для базового примера. Вам просто нужно убедиться, что вы не помещаете чистые данные области запроса или сеанса в область приложения.

16 голосов
/ 10 февраля 2010
1 голос
/ 10 февраля 2010

Ого, это загруженный вопрос.

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

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

Разработка параллельного приложения не проста, и нет волшебной палочки (к сожалению). Я настоятельно рекомендую книгу " Параллелизм Java на практике " для получения дополнительной информации о написании безопасного параллельного кода.

0 голосов
/ 10 февраля 2010

Вы имеете в виду в контексте, в отличие от любого другого Java-приложения? Там действительно нет большой разницы. Каждый запрос к сервлету заставляет контейнер выдавать новый поток для его обработки, поэтому переменные экземпляра внутри сервлета должны быть поточно-ориентированными. Лучше обрабатывать весь ваш бизнес с локальными переменными в методах doGet / doPost (). Есть одна ошибка, о которой я могу подумать. С переменными сеанса может случиться так, что у пользователя открыты два окна браузера, каждое из которых указывает на ваше приложение. В этом случае вам также следует следить за безопасностью потоков с помощью области действия сеанса.

...