[개발팁] Spring + Quartz에서 작업의 동시실행을 막는 방법

예약작업이 흔히 DB나 파일을 다루다보니 작업이 한번에 하나씩만 실행되어야할때가 많습니다.. 예를 들어 디렉토리를 폴링하는 경우 선행 작업이 끝나지 않은 상태에서 다음 작업이 실행된다면 하나의 파일을 동시에 두개의 작업이 처리할 지도 모르니까요..

스프링 스케쥴링 문서를 보면 “MethodInvokingJobDetailFactoryBean”을 사용하는 경우 “concurrent” 값을 설정하는 것만으로 이 문제가 간단히 해결됩니다..

<bean id=”jobDetail” class=”org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean“>
<property name=”targetObject” ref=”exampleBusinessObject” />
<property name=”targetMethod” value=”doIt” />
<property name=”concurrent” value=”false” />
</bean>


그런데 아래와같이 “JobDetailBean”을 이용하는 경우라면 어떻게하면될까요??

<bean name=”exampleJob” class=”org.springframework.scheduling.quartz.JobDetailBean“>
<property name=”jobClass” value=”example.ExampleJob” />
</bean>


방법은 간단합니다.. 위 “ExampleJob” 클래스를 만들때 “implements org.quartz.StatefulJob”을 해주면 됩니다.. 그런데 요건이 바뀌어 동시 실행을 허용하려면 클래스를 수정해야겠네요.. ㅡ..ㅡ

“JobDetailBean”을 이용하면서도 위 “concurrent”처럼 설정으로 해결할 수 있는 방법을 찾아봤습니다.. 그런데 못찾겠더라구요.. 해서.. 걍.. 자체 구현을 하기로 결심했습니다.. ㅎㅎ.. 나중에라도 누군가 방법을 찾게되면 저에게도 좀 알려주시길.. ^^;;

찾아보니.. “implements org.quartz.StatefulJob”을 하는 것은 “JobDetailBean”의 “isStateful()”이라는 메소드에 영향을 줍니다.. “JobDetailBean”을 상속한 새로운 “MyJobDetailBean”을 만들었습니다..

public class MyJobDetailBean extends JobDetailBean {

boolean concurrent = false;

public void setConcurrent(boolean concurrent) {
this.concurrent = concurrent;
}

public boolean isStateful() {
return !concurrent;
}
}

 

<bean name=”exampleJob” class=”myproject.MyJobDetailBean“>
<property name=”jobClass” value=”example.ExampleJob” />
<property name=”concurrent” value=”false” />
</bean>


프로퍼티명을 “stateful”이라고 하지않고 “concurrent”라고 한 것은 위 설정이 상태유지를 의미하지는않기때문입니다..

어쨌건.. 잘 돌아가는 것 같습니다.. ㅎㅎ..

※ 한가지 참고할게 있습니다..

매분 0초에 작업을 실행하도록 설정했을때
0분 0초에 시작한 작업이 1분 10초에 끝나다고 가정해보면..
다음번 작업은 언제 실행될까요??

1) 1분 0초에 실행하기로 되어있던 작업은 무시되고 2분 0초에 시작된다..
2) 선행작업이 끝나자마자 대기중인 작업이 바로 시작된다.. 즉.. 1분 10초에 시작된다..

테스트를 해보니.. 2)번이네요..