2013년 4월 2일 화요일

Tomcat 서버 + Timer 작업 (스케줄 작업)

참고: http://stackoverflow.com/questions/791986/background-thread-for-a-tomcat-servlet-app

ServletContextListener 를 이용하여 앱이 시작할 때와 앱이 종료할 때 이벤트를 처리할 수 있다.

앱이 시작할 때 schedule 작업하는 thread 를 시작하고 앱이 종료할 때 thread 를 종료하는 방식을 응용해 봤다.

web.xml 에 우리의 listener 클래스를 등록한다.
<listener>
    <listener-class>com.sample.SampleListener</listener-class>
</listener>

Listener 클래스는 대략 아래와 같다.
package com.sample;

public class SampleListener implements ServletContextListener {

    private MyThread myThread = null;
 
    /**
     * 앱 시작시 불리는 함수
     */
    public void contextInitialized(ServletContextEvent sce) {
        if ((myThread == null) || (!myThread.isAlive())) {
            myThread = new MyThread(new MyTask());
            myThread.start();
        }
    }
    /**
     * 앱 종료시 불리는 함수 
     */
    public void contextDestroyed(ServletContextEvent sce){
        if (myThread != null && myThread.isAlive()) {
            myThread.quit();
        }
    }
}

실제 작업하는 스레드는 TimerTask 를 등록하고 작업이 진행되는 동안 대기하는 일을 한다.
예) 매분마다 특정 파일(backup.bat) 을 실행한다.
/**
 * 실제 작업하는 클래스
 */ 
public static class MyTask extends TimerTask {

    @Override
    public void run() {
        
        try {
            ProcessBuilder builder = new ProcessBuilder("c:\\bin\\backup.bat");
            Process p = builder.start();
            InputStream in = p.getInputStream();
            while (in.read() != -1) {
                Thread.sleep(10);
            }
            p.waitFor();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

/**
 * 앱이 실행되는 동안 작업을 기다리는 스레드
 */
public static class MyThread extends Thread {
    
    private boolean done = false;
    private Timer timer;
    private TimerTask task;
    
    public MyThread (TimerTask task) {
        this.task = task;
    }
    
    public void quit() {
        this.done = true;
        this.interrupt();
    }
    
    public boolean finishing() {
        return (done || Thread.interrupted());
    }

    @Override
    public void run() {
        super.run();
        
        timer = new Timer();
        
        Calendar now = Calendar.getInstance();
        timer.scheduleAtFixedRate(task, now.getTime(), 1000 * 60);
        
        while (!finishing()) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                break;
            }
        }
        
        timer.cancel();
    }
}


댓글 없음:

댓글 쓰기