SingleThreadModel устарела и не гарантирует безопасность потоков, каков наилучший подход к решению / дизайну, чтобы гарантировать безопасность потоков в сервлете? - PullRequest
0 голосов
/ 29 декабря 2018

Я хочу гарантировать безопасность ниток в одном из моих Servlet.SingleThreadModel устарело и не гарантирует безопасность потока.Вместо этого я могу использовать synchronized блок внутри моего Servlet.

Является ли ты альтернативным способом гарантировать безопасность потоков в сервлете?

ЕслиДа , Пожалуйста, объясните, как мне этого добиться.

Если нет , каким будет мой подход к проектированию, гарантирующий безопасность потоков в Servlet?

1 Ответ

0 голосов
/ 29 декабря 2018

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

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

Один из популярных методов построения приложений - разделить (логически и физически) ваш код на три части: m odel (ваши данные), v iew (UI) и контроллер c - обычно сокращенно обозначаются как "MVC".Когда вы делаете это, вы рассматриваете «представление» и «контроллер» как без состояний .Таким образом, модель содержит все состояние программы / пользователя / транзакции / чего угодно, а контроллер и представление просто изменяют это состояние по мере необходимости и позволяют этой модели проходить через код.

Контейнер сервлета, сам сервлет является либо контроллером (или представлением) и должен быть без состояний.Это очень легко сделать: просто не используйте членов класса, которые содержат что-либо, что зависит от пользователя или транзакции.Любые члены класса Servlet должны быть поточно-ориентированными (например, ConcurrentMap) или использоваться поточно-ориентированным способом (например, synchronized блокирует доступ к HashMap).Помните, что даже потокобезопасную коллекцию (например, ConcurrentMap) можно использовать не поточно-безопасным способом, например:

ConcurrentMap cm = ...;
if(!cm.containsKey("foo")) {
    cm.put("foo", createFoo());
}

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

Итак, где вы разместите модель?Ну, есть несколько вариантов для этого.Один из самых простых способов - сохранить все в пользовательском session.Сеанс - это структура, специфичная для пользователя и доступная всем объектам HttpServletRequest, поэтому он всегда доступен сервлету.Это работает, только если пользователи действительно входят в ваше приложение.Давайте пока предположим, что у вас есть пользователи, и у них есть свои собственные сеансы.

Сеанс автоматически связывается с запросом на основе личности пользователя, выполняющего запрос.Любые другие данные, которые вам нужны, должны поступать из самого запроса (вероятно, запрос параметры , который поступает из строки запроса ).

Вы можете поместить все, что захотитесессия.Пользовательские классы, которые описывают ваши «бизнес-объекты» (вещи, которые вы используете для представления концептов в вашем конкретном приложении), предпочтительнее, чем Map объекты, которые содержат именованные коллекции других Map s, Lists s и т. Д.видел законченные веб-приложения, построенные только на стандартных классах библиотеки Java, и они представляют собой беспорядок в поисках по карте и в магических списках-индексах.Не попадайтесь в эту ловушку: пишите свои собственные классы.

Другой вариант для данных пользовательской модели - сохранить их в какой-либо базе данных.Существует много вариантов «базы данных» от простых хранилищ файлов до реляционных баз данных до хранилищ документов / столбцов / индексов.Все они имеют свои сильные и слабые стороны.Но они хранят данные, и вы можете поместить данные модели пользователя в базу данных.Как вы идентифицируете пользователя?Вероятно, сохраняя идентификатор пользователя в сеансе.(Так что обычно все возвращается на сессии).Вы также можете использовать имя пользователя (доступно из запроса) для поиска данных пользователя в базе данных.

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

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

...