내용 목차
본 장에서는 Jakarta Concurrency에서 제공하는 Managed Objects에 대해서 간략하게 설명하고 사용 예제를 기술한다.
javax.enterprise.concurrent.ManagedExecutorService 인터페이스는 Java SE의 java.util.concurrent.ExecutorService 인터페이스를 상속한다. ExecutorService와 동일하게 비동기 작업을 수행하기 위해 이용되고, 애플리케이션 서버는 비동기로 실행되는 작업의 컨텍스트 정보를 유지시켜준다.
다음은 ManagedExecutorService를 리소스로 정의한 예제이다.
[예 2.1] ManagedExecutorService를 리소스로 정의한 예제 : <<domain.xml>>
<domain> ... <server> <data-sources> <data-source>testdb</data-source> </data-sources> <managed-executor-service>mes1</managed-executor-service> </server> <resources> <managed-executor-service> <export-name>mes1</export-name> <long-running-task>true</long-running-task> <thread-pool> <min>10</min> <max>20</max> <keep-alive-time>60000</keep-alive-time> <queue-size>4096</queue-size> </thread-pool> </managed-executor-service> </resources> ... </domain>
다음은 ManagedExecutorService를 활용한 애플리케이션 예제이다.
[예 2.2] ManagedExecutorService를 활용한 애플리케이션 예제
public class AppServlet extends HTTPServlet implements Servlet { // Retrieve our executor instance. @Resource(name=mes1”) ManagedExecutorService mes; protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ArrayList<Callable> builderTasks = new ArrayList<Callable>(); builderTasks.add(new AccountTask(reqID, accountID)); builderTasks.add(new InsuranceTask(reqID, accountID)); // Submit the tasks and wait. List<Future<Object>> results = mes.invokeAll(builderTasks); AccountInfo accountInfo = (AccountInfo) results.get(0).get(); InsuranceInfo insInfo = (InsuranceInfo) results.get(1).get(); // Process the results } }
WebAdmin에서는 왼쪽 메뉴에서 [Resources] > [Concurrency Utilities Resource]를 선택해서 ManagedExecutorService 설정을 할 수 있다.
javax.enterprise.concurrent.ManagedExecutorService 인터페이스는 ManagedExecutorService의 모든 기능을 상속받는 동시에 Java SE의 java.util.concurrent.ScheduledExecutorService의 기능을 상속받아 작업의 지연 실행이나 주기적 실행이 가능하도록 기능을 제공한다. 추가적으로 Trigger와 ManagedTaskListener 인터페이스를 통해 작업의 실행을 제어할 수 있도록 한다.
다음은 ManagedScheduledExecutorService를 리소스로 정의한 예제이다.
[예 2.3] ManagedScheduledExecutorService를 리소스로 정의한 예제 : <<domain.xml>>
<domain> ... <server> <data-sources> <data-source>testdb</data-source> </data-sources> <managed-scheduled-executor-service>mses1</managed-scheduled-executor-service> </server> <resources> <managed-scheduled-executor-service> <export-name>mses1</export-name> <long-running-task>true</long-running-task> <thread-pool> <min>10</min> <max>20</max> <keep-alive-time>60000</keep-alive-time> <queue-size>4096</queue-size> </thread-pool> </managed-scheduled-executor-service> </resources> ... </domain>
다음은 ManagedScheduledExecutorService를 활용한 애플리케이션 예제이다.
[예 2.4] ManagedScheduledExecutorService를 활용한 애플리케이션 예제
public class AppServlet extends HTTPServlet implements Servlet { @Resource(name=mses1”) ManagedScheduledExecutorService mses; protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Runnable printTask = new Runnable() { @Override public void run() { System.out.println(System.currentTimeMillis()); } }; // printTask가 5초마다 주기적으로 실행됨 mses.schedule(printTask, 5, TimeUnit.SECONDS); } }
WebAdmin 왼쪽 메뉴의 [Resources] > [Concurrency Utilities Resource]에서 ManagedScheduledExecutorService 설정을 할 수 있다.
ExecutorService를 이용하지 않고 ContextService를 통해 Managed Task를 생성하는 방식을 제공한다. 본 기능을 이용하여 사용자는 태스크를 만들 때 컨텍스트에 대해서 신경쓰지 않아도 애플리케이션 서버 내부적으로 작업이 실행될 때 컨텍스트를 유지시켜준다. 좀더 상세하게는 Dynamic Proxy를 이용해서 현재 작업을 실행하기 전에 해당 스레드에 컨텍스트를 설정하고 작업을 수행한다. 모든 작업이 완료되면 컨텍스트를 복귀하는 작업을 대신 수행한다.
다음은 ContextService를 리소스로 정의한 예제이다.
[예 2.5] ContextService를 리소스로 정의한 예제 : <<domain.xml>>
<domain> ... <server> <data-sources> <data-source>testdb</data-source> </data-sources> <context-service>cs1</context-service> </server> <resources> <context-service> <export-name>cs1</export-name> </context-service> </resources> ... </domain>
다음은 ContextService를 활용한 애플리케이션 예제이다.
[예 2.6] ContextService를 활용한 애플리케이션 예제
public class AppServlet extends HTTPServlet implements Servlet { @Resource(name=cs1”) ContextService cs; protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 일반적인 Runnable task Runnable simpleTask = new Runnable() { @Override public void run() { int sum = 0; for (int i = 0; i < 10; i++) { sum += i; } System.out.println(sum); } }; // 일반 task를 ContextService를 통해서 Contextual task로 만듦 cs.createContextualProxy(simpleTask, Runnable.class); // SE에서 제공하는 Executor에 Contextual task를 넘김 ExecutorService es = Executors.newFixedThreadPool(1); es.submit(simpleTask); } }
WebAdmin 왼쪽 메뉴의 [Resources] > [Concurrency Utilities Resource]에서 ContextService 설정을 할 수 있다.
javax.enterprise.concurrent.ManagedThreadFactory 인터페이스는 Java SE의 java.util.concurrent.ThreadFactory 기능을 상속받아 스레드를 생성하는 기능을 제공한다. 일반적으로 ThreadFactory는 ThreadPoolExecutor를 생성할 때 생성자의 파라미터로 넘기는 곳에 사용한다. 따라서, Java SE의 Concurrency API 상에서도 worker 스레드가 작업을 실행할 때 Task에 대한 컨텍스트를 유지해줄 수 있다.
다음은 ManagedThreadFactory를 리소스로 정의한 예제이다.
[예 2.7] ManagedThreadFactory를 리소스로 정의 예제 : <<domain.xml>>
<domain> ... <server> <data-sources> <data-source>testdb</data-source> </data-sources> <managed-thread-factory>mtf1</managed-thread-factory> </server> <resources> <managed-thread-factory> <export-name>mtf1</export-name> <thread-priority>5</thread-priority> </managed-thread-factory> </resources> ... </domain>
다음은 ManagedThreadFactory를 활용한 애플리케이션 예제이다.
[예 2.8] ManagedThreadFactory를 활용한 애플리케이션 예제
public class AppServlet extends HTTPServlet implements Servlet { // Retrieve our executor instance. @Resource(name=mtf1”) ManagedThreadFactory mtf; protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 일반적인 Runnable task Runnable simpleTask = new Runnable() { @Override public void run() { int sum = 0; for (int i = 0; i < 10; i++) { sum += i; } System.out.println(sum); } }; // simpleTask를 ManagedThreadFactory에서 제공되는 thread에서 실행 mtf.newThread(simpleTask).start(); // 혹은 ThreadPoolExecutor의 매개변수로 ThreadFactory를 전달 Executor e = new ThreadPoolExecutor(5, 10, 6L, TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(4096), mtf); e.execute(new SimpleTask()); } }
WebAdmin에서는 왼쪽 메뉴의 [Resources] > [Concurrency Utilities Resource]에서 ManagedThreadFactory 설정을 할 수 있다.