제2장 Managed Objects

내용 목차

2.1. ManagedExecutorService
2.2. ManagedScheduledExecutorService
2.3. ContextService
2.4. ManagedThreadFactory

본 장에서는 Concurrency Utilities for Java EE에서 제공하는 Managed Objects에 대해서 간략하게 설명하고 사용 예제를 기술한다.

2.1. ManagedExecutorService

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 예제

WebAdmin에서는 왼쪽 메뉴에서 [Resources] > [Concurrency Utilities Resource]를 선택해서 ManagedExecutorService 설정을 할 수 있다.

[그림 2.1] WebAdmin에서 ManagedExecutorService 설정

WebAdmin에서 ManagedExecutorService 설정


2.2. ManagedScheduledExecutorService

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 예제

WebAdmin 왼쪽 메뉴의 [Resources] > [Concurrency Utilities Resource]에서 ManagedScheduledExecutorService 설정을 할 수 있다.

[그림 2.2] WebAdmin에서 ManagedScheduledExecutorService 설정

WebAdmin에서 ManagedScheduledExecutorService 설정


2.3. ContextService

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 예제

WebAdmin 왼쪽 메뉴의 [Resources] > [Concurrency Utilities Resource]에서 ContextService 설정을 할 수 있다.

[그림 2.3] WebAdmin에서 ContextService 설정

WebAdmin에서 ContextService 설정


2.4. ManagedThreadFactory

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 예제

WebAdmin에서는 왼쪽 메뉴의 [Resources] > [Concurrency Utilities Resource]에서 ManagedThreadFactory 설정을 할 수 있다.

[그림 2.4] WebAdmin에서 ManagedThreadFactory 설정

WebAdmin에서 ManagedThreadFactory 설정