Сведения о жизненном цикле Java EE и деталях, связанных с параллелизмом, могут быть не новы для опытных профессионалов, но для новичков это может занять некоторое время.
Что касается EJB, понимание их жизненного цикла (и связанных сценариев параллелизма) крайне важно для обеспечения надлежащего использования и разработки решения с использованием EJB. Злоупотреблять ими легко!
Я быстро расскажу о бинах без гражданства и о состоянии в этом посте и пока пропущу бобы Лимы!
- Stateful Session Beans — жизненный цикл + обработка параллелизма
- Бины без сохранения состояния — только модель параллелизма, поскольку я кратко рассмотрел жизненный цикл в одной из моих предыдущих публикаций .
Каковы различные состояния в жизненном цикле сессионного компонента с состоянием?
- Не существует
- готовы
- Пассивированная
Как меняются штаты? Что их вызывает?
Вот быстрый снимок в виде таблицы и диаграмма высокого уровня. Для более подробной информации читайте дальше. , ,
Примечание : DNE — не существует, R — готово, P — пассивировано, SFSB — сессионный компонент с сохранением состояния
Государственный переход | Триггеры | Callbacks |
---|---|---|
DNE к R | При первом обращении к экземпляру SFSB через JNDI или DI | @PostConstruct |
R в DNE | Контейнер закрывается, клиент вызывает метод, аннотированный @Remove, бин достигает порога простоя, обозначенного DD или @StatefulTimeout | @PreDestroy |
R к P | Контейнер EJB пассивирует неиспользуемые компоненты и удаляет их из активной памяти на основе определенных алгоритмов. | @PrePassivate |
P к DNE | Компонент достигает порога простоя, обозначенного DD или @StatefulTimeout | Примечание : аннотированный метод @PreDestroy НЕ вызывается |
P к R | Когда клиент вызывает экземпляр SFSB после его пассивации, но время еще не истекло | @PostActivate |
Примечание . Если SFSB генерирует исключение во время обработки запроса, его экземпляр уничтожается, т.е. он переходит в состояние DNE. В этом случае аннотированный метод @PreDestroy не вызывается
Теперь, когда у нас есть некоторое представление о жизненном цикле SFSB, давайте попробуем взглянуть на то, как эти бины ведут себя под нагрузкой, т.е. когда приложение используется несколькими пользователями одновременно, что приводит к одновременному доступу экземпляров SFSB.
Сессионные компоненты Stateful: управление параллелизмом
Безопасность потоков — одна из основных функций EJB. Следует отметить, что эта безопасность потока бесплатна и не требует каких-либо связанных с параллелизмом конструкций, которые должны быть закодированы самим разработчиком компонента (есть несколько исключений ). Что касается SFSB, контейнер EJB гарантирует, что только один поток может получить доступ к экземпляру компонента в определенный момент времени.
В этом примере мы пытаемся симулировать одновременный доступ к одному экземпляру SFSB, вызывая тестовый сервлет через JMeter . Сервлет вводит компонент через DI и вызывает для него метод. Метод SFSB просто использует Thread.sleep (), чтобы притворяться, будто он что-то выполняет.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package com.abhirockzz.wordpress.ejb.lifecycle.stateful; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.Stateful; @Stateful public class MyStatefulBean { public MyStatefulBean() { } public void act() { System.out.println( "Entered MyStatefulBean/act() on " + new Date().toString() + " . SFSB instance " + this .hashCode() + " Thread : " + Thread.currentThread().getName()); try { Thread.sleep( 2000 ); } catch (InterruptedException ex) { Logger.getLogger(MyStatefulBean. class .getName()).log(Level.SEVERE, null , ex); } System.out.println( "Exit MyStatefulBean/act() on " + new Date().toString() + " . SFSB instance " + this .hashCode() + " Thread : " + Thread.currentThread().getName()); } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package com.abhirockzz.wordpress.ejb.lifecycle.stateful; import java.io.IOException; import java.util.Date; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet (name = "SFSBTestServlet" , urlPatterns = { "/SFSBTestServlet" }) public class SFSBTestServlet extends HttpServlet { public SFSBTestServlet() { } @Inject MyStatefulBean mySFSB; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println( "Entered SFSBTestServlet/doGet() on " + new Date().toString() + " . Servlet instance " + this .hashCode() + " Thread : " + Thread.currentThread().getName()); mySFSB.act(); } } |
наблюдения
- Поскольку сам сервлет не является потокобезопасным, на самом деле несколько потоков будут входить в метод doGet ()
- Единственный экземпляр SFSB (очевидный через результат hashCode) при одновременном доступе (см. Имена потоков в записанных инструкциях)
- Только один поток сможет получить доступ к экземпляру SFSB — другие потоки ждут своей очереди, пока метод SFSB не вернется. Эта задержка заметна через лог-операторы на консоли
А как насчет бобов без гражданства?
Эти бобы по своей природе являются потокобезопасными . Почему ? Это связано с тем, что по умолчанию контейнер обеспечивает обслуживание каждого нового запроса новым экземпляром компонента. Помните, что клиент может получить ссылку на bean-компонент без состояния тремя возможными способами — DI, JNDI или через удаленный интерфейс (RMI). Во всех этих случаях это контейнер (прокси), который перехватывает вызов — таким образом, даже если несколько потоков, по-видимому, обращаются к одному и тому же экземпляру компонента, на самом деле это не один и тот же!
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.abhirockzz.wordpress.ejb.lifecycle.stateless; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.Stateless; @Stateless public class MyStatelesslBean { public void act() { System.out.println( "Entered MyStatelesslBean/act() on " + new Date().toString() + " . SLSB instance " + this .hashCode() + " Thread : " + Thread.currentThread().getName()); try { Thread.sleep( 2000 ); } catch (InterruptedException ex) { Logger.getLogger(MyStatelesslBean. class .getName()).log(Level.SEVERE, null , ex); } System.out.println( "Exit MyStatelesslBean/act() on " + new Date().toString() + " . SLSB instance " + this .hashCode() + " Thread : " + Thread.currentThread().getName()); } } |
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package com.abhirockzz.wordpress.ejb.lifecycle.stateless; import java.io.IOException; import java.util.Date; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet (name = "SLSBTestServlet" , urlPatterns = { "/SLSBTestServlet" }) public class SLSBTestServlet extends HttpServlet { @Inject MyStatelesslBean slsb; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println( "Entered SLSBTestServlet/doGet() on " + new Date().toString() + " . Servlet instance " + this .hashCode() + " Thread : " + Thread.currentThread().getName()); slsb.act(); } } |
наблюдения
- Поскольку сам сервлет не является потокобезопасным, на самом деле несколько потоков будут входить в метод doGet ()
- Контейнер выбирает различные экземпляры SLSB (что видно из результата hashCode ) для управления параллельными запросами (см. Имена потоков в записанных инструкциях).
- Несмотря на одновременные запросы, каждый поток запросов обслуживается новым экземпляром
На этом пока все! Я планирую рассказать о бинах Singleton Session в следующем посте. Оставайтесь в курсе . , , ,
Спасибо за чтение!
Ссылка: | EJB 3.x: модели жизненного цикла и параллелизма (часть 1) от нашего партнера JCG Абхишека Гупты в блоге Object Oriented .. |