Skip to content
Home » 자바 스케줄러 구현 | Node Js – 스케줄러 구현 상위 200개 답변

자바 스케줄러 구현 | Node Js – 스케줄러 구현 상위 200개 답변

당신은 주제를 찾고 있습니까 “자바 스케줄러 구현 – Node js – 스케줄러 구현“? 다음 카테고리의 웹사이트 https://kk.taphoamini.com 에서 귀하의 모든 질문에 답변해 드립니다: https://kk.taphoamini.com/wiki/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 개발자의품격 이(가) 작성한 기사에는 조회수 2,499회 및 좋아요 40개 개의 좋아요가 있습니다.

Table of Contents

자바 스케줄러 구현 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

d여기에서 Node js – 스케줄러 구현 – 자바 스케줄러 구현 주제에 대한 세부정보를 참조하세요

[개발자의 품격] 품격있는 개발자 되기!
이번시간에는 node-schedule 이라는 모듈을 설치하고, 스케줄러 기능을 빠르게 구현을 해봅니다.
스케줄러는 특정일자/요일/시간/분/초에 지정된 프로그램을 동작시키게 해줍니다.

자바 스케줄러 구현 주제에 대한 자세한 내용은 여기를 참조하세요.

자바 스프링 스케줄러 구현과 실행 cron 표현식 사용 – 개코

자바 스프링에서는 cron 표현식을 사용하여 스케줄러를 만들 수 있다. cron 표현식을 반복적인 시간표현을 말한다. 스프링 스케줄러를 구현하고 실행 …

+ 여기에 자세히 보기

Source: lngnat.tistory.com

Date Published: 7/7/2021

View: 7182

[JAVA] Quartz 스케줄러 만들기 (1) – 실행 – 개발하는 도치

– jdk-11.0.5 · – quartz-2.3.2 · – · – 실제 작업을 수행하는 객체 · – org.quartz.Job 인터페이스를 상속받아 execute 메소드에 수행 로직을 구현 · – 같은 …

+ 여기에 더 보기

Source: heodolf.tistory.com

Date Published: 5/26/2022

View: 8701

[Spring] cron으로 스케쥴링 구현하기 (쉽고 자세한 설명)

Programming/Java. [Spring] cron으로 스케쥴링 구현하기 (쉽고 자세한 설명) … 회사에서 스케쥴링 구현으로 4시간 동안 삽질해서 알아냈다.

+ 여기를 클릭

Source: in0-pro.tistory.com

Date Published: 9/29/2022

View: 7456

java scheduler / 자바 스케줄러 예제 – 네이버 블로그

여기가 자바 스케줄러 구현을 위해 사용한 supinan framwork 를 받을 수 있는 곳인데요. 빨간 동그라미에 다운로드 써있는걸 누르시면 라이브러리를 …

+ 여기에 보기

Source: m.blog.naver.com

Date Published: 6/28/2021

View: 6035

JAVA 스케줄러 @Scheduled 활용 – velog

JAVA로 EgovFrame 환경에서 @Scheduled을 활용하여 스케줄러를 구현했다.(1) dispatcher-servlet에서 task NameSpace를 추가하였다.

+ 여기에 보기

Source: velog.io

Date Published: 9/18/2021

View: 3968

[JAVA] @Scheduled – 스케줄러 사용법 – 개발공작소 – 티스토리

스케줄러를 이용하여 구현 하는 김에 스케줄러를 정리한다. @Scheduled 주기적인 작업이 있을 때 @Scheduled 어노테이션을 사용하면 쉽게 적용이 가능 …

+ 여기에 자세히 보기

Source: bongra.tistory.com

Date Published: 9/29/2022

View: 9509

[JAVA] 스케줄러(Quartz) 실행하는 법 – 오달달의 오두막

JAVA에서는 Quartz라는 lib을 이용해서 스케줄러를 구현할 수 있다. 메인메소드를 통해 일정한 주기로 작업을 실행하는 스케줄러를 만들어보겠다.

+ 여기에 표시

Source: ohdaldal.tistory.com

Date Published: 8/5/2021

View: 8971

ThreadPoolTaskScheduler를 이용하여 자바 스케줄러 구현 및 …

ThreadPoolTaskScheduler를 이용하여 자바 스케줄러 구현 및 강제종료 구현. 방구석개발자 2021. 8. 2. 14:15. 반응형. 안녕하세요. 방구석 개발자입니다.

+ 여기에 더 보기

Source: roomconerdeveloper.tistory.com

Date Published: 4/16/2022

View: 5528

Java에서 주기적으로 작업 실행 – Techie Delight

이 게시물은 Java 애플리케이션에서 반복 실행을 위한 작업을 예약하는 방법에 대해 설명 … 실행 일정을 설명하려면 다음을 구현해야 합니다. scheduler() 방법.

+ 여기를 클릭

Source: www.techiedelight.com

Date Published: 4/22/2021

View: 8381

Java Quartz Scheduler – Job Chaining 구현 – 뒤태지존의 …

Java로 Job Scheduling을 쉽게(참 조심스러운 단어.. ㅋㅋ) 할 수 있게 해주는 쿼츠(Quartz) 스케줄러가 있다. 이 사이트에 나와있는 문서들은 여태 본 …

+ 여기에 보기

Source: homoefficio.github.io

Date Published: 10/21/2021

View: 2604

주제와 관련된 이미지 자바 스케줄러 구현

주제와 관련된 더 많은 사진을 참조하십시오 Node js – 스케줄러 구현. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

Node js  - 스케줄러 구현
Node js – 스케줄러 구현

주제에 대한 기사 평가 자바 스케줄러 구현

  • Author: 개발자의품격
  • Views: 조회수 2,499회
  • Likes: 좋아요 40개
  • Date Published: 2020. 12. 10.
  • Video Url link: https://www.youtube.com/watch?v=zajq7NJflPY

자바 스프링 스케줄러 구현과 실행 cron 표현식 사용

반응형

프로그램을 통해 반복적인 일을 위해 스케줄러를 만든다. 자바 스프링에서는 cron 표현식을 사용하여 스케줄러를 만들 수 있다. cron 표현식을 반복적인 시간표현을 말한다. 스프링 스케줄러를 구현하고 실행해 본다.

스케줄러 구현하기

servlet-context.xml 파일에 스케줄러 환경설정하기 스케줄러 구현하기 실행화면 동작확인하기

servlet-context.xml 파일에 스케줄러 환경설정하기

먼저, servlet-context.xml 에 job scheduler 관련한 환경설정을 추가해야 한다.

아래의 코드는 job scheduler 를 servlet-context.xml 에 추가할 것이다.

xmlns:task=”http://www.springframework.org/schema/task http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd

위의 추가할 코드를 아래의 전체적인 코드 servlet-context.xml 파일을 확인하여 추가하도록 한다.

스케줄러 구현하기

자바 @Component 클래스 파일을 만들고 @Scheduled 메서드를 추가하여 스케줄러를 위한 코드를 만든다.

이렇게 만들어 주면 아파치 서버가 실행되며 자동으로 등록이 된다.

package com.crd.test; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * Handles requests for the application home page. */ @Component public class ScheduleController { /*** 1초마다 실행 */ @Scheduled(cron = “0/1 * * * * *”) public void CronScheduler() { LocalDateTime vLocalDateTime = LocalDateTime.now(); DateTimeFormatter vDateTimeFormatter = DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:ss.SSS”); System.out.println(“Cron 스케줄러 : ” + vLocalDateTime.format(vDateTimeFormatter)); } }

실행 화면 동작 확인하기

아파치 서버를 실행하고 위의 코드는 테스트를 위해 1초마다 자동으로 실행되는 것을 볼 수 있다. 이것만 할 수 있다면 자동으로 할 수 있는 유용한 것들이 많이 있다.

반응형

[JAVA] Quartz 스케줄러 만들기 (1) – 실행

서론

예전에 커뮤니티 사이트에서 글목록을 수집하고 DB에 저장하는 크롤러를 만든적이 있었다. 이 때, 주기적으로 실행하기 위해서 crontab이나 Windows 작업 스케줄러를 사용했다. 이 두개의 스케줄러는 사용하기는 편하지만 프로그램과 스케줄을 별도로 관리해야하기 때문에 관리포인트가 늘어나는 단점이 있다.

그래서, 이번에는 스케줄러를 직접 만들어보려고 하는데 Spring Batch는 써본적이 있기 때문에 이번에는 Quartz로 만들어 보려고 한다.

개발환경

– jdk-11.0.5

– quartz-2.3.2

org.quartz-scheduler quartz 2.3.2

Quartz란?

– Java Scheduling 라이브러리.

– 일련의 작업들을 단발성, 주기성으로 실행할 수 있음.

구성요소

1. JOB

– 실제 작업을 수행하는 객체

– org.quartz.Job 인터페이스를 상속받아 execute 메소드에 수행 로직을 구현

– 같은 그룹에는 동일한 이름을 가진 Job을 생성할 수 없음

2. Trigger

– Job을 수행하기위한 조건(스케줄)을 정의한 객체

– 특정시간, 횟수, 반복주기 등을 설정할 수 있음

* 특정시간 및 횟수: SimpleTrigger

* 주기적으로 반복: CronTrigger

– 같은 그룹에는 동일한 이름을 가진 Job을 생성할 수 없음

– Job : Trigger = 1 : N

3. Listener

– 작업의 시작, 중간, 끝, 에러를 처리할 수 있는 객체

– ScheduleListener와 TriggerListener

소스코드

1. SampleJobExecutor.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.quartz.CronExpression; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.Job; import org.quartz.JobBuilder; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.SimpleTrigger; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; import sch.listeners.MyScheduleListener; import sch.listeners.MyTriggerListener; /** * Quartz Job */ public class SampleJobExecutor implements Job { private static final SimpleDateFormat TIMESTAMP_FMT = new SimpleDateFormat( “yyyy-MM-dd hh:mm:ss.SSSS” ); @Override public void execute(JobExecutionContext ctx) throws JobExecutionException { JobDataMap jobDataMap = ctx.getJobDetail().getJobDataMap(); String currentDate = TIMESTAMP_FMT. format ( new Date()); String triggerKey = ctx.getTrigger().getKey(). toString (); String message = jobDataMap.getString( “message” ); System . out . println ( String . format ( “[%s][%s] %s” , currentDate, triggerKey, message )); } } /** * Quartz Scheduler 실행 */ class JobLuacher { public static void main( String [] args) { try { // Scheduler 생성 SchedulerFactory factory = new StdSchedulerFactory(); Scheduler scheduler = factory.getScheduler(); scheduler.getListenerManager().addJobListener( new MyScheduleListener()); scheduler.getListenerManager().addTriggerListener( new MyTriggerListener()); // Scheduler 실행 scheduler.start(); // JOB Data 객체 생성 JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put( “message” , “Hello, Quartz!!!” ); // JOB Executor Class Class < ? extends Job > jobClass = SampleJobExecutor. class ; // JOB 생성 JobDetail jobDetail = JobBuilder.newJob(jobClass) .withIdentity( “job_name” , “job_group” ) .setJobData(jobDataMap) .build(); // SimpleTrigger 생성 // 4초마다 반복하며, 최대 5회 실행 SimpleScheduleBuilder simpleSch = SimpleScheduleBuilder.repeatSecondlyForTotalCount( 5 , 4 ); SimpleTrigger simpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger() .withIdentity( “simple_trigger” , “simple_trigger_group” ) .withSchedule(simpleSch) .forJob(jobDetail) .build(); // CronTrigger 생성 // 15초주기로 반복( 0, 15, 30, 45 ) CronScheduleBuilder cronSch = CronScheduleBuilder.cronSchedule( new CronExpression( “0/15 * * * * ?” )); CronTrigger cronTrigger = (CronTrigger) TriggerBuilder.newTrigger() .withIdentity( “cron_trigger” , “cron_trigger_group” ) .withSchedule(cronSch) .forJob(jobDetail) .build(); // JobDtail : Trigger = 1 : N 설정 Set < Trigger > triggerSet = new HashSet < Trigger > (); triggerSet. add (simpleTrigger); triggerSet. add (cronTrigger); // Schedule 등록 scheduler.scheduleJob(jobDetail, triggerSet, false ); } catch (ParseException | SchedulerException e) { e.printStackTrace(); } } } Colored by Color Scripter cs

실행결과

마치며

이것으로 간단하게 Quartz로 스케줄러를 만들고 실행하는 방법에 대해서 알아보았다. 만들어보니 Spring Batch보다 훨씬 간단했다. 다만, 스케줄을 Annotation으로 등록할 수 있는 Spring Batch와는 다르게 Trigger 객체를 생성해야하는 번거로움이 있다. 그래도, Quartz가 좀 더 직관적이라 마음에 든다.

[Spring] cron으로 스케쥴링 구현하기 (쉽고 자세한 설명)

728×90

회사에서 스케쥴링 구현으로 4시간 동안 삽질해서 알아냈다..

초등학생도 알기 쉽게 차근차근 설명해드림!

(spring 프로젝트를 생성했다는 가정 하에 시작함)

1. 스케쥴러 로직이 들어갈 자리를 만들어주자.

아직 갓 생성한 프로젝트라 들어있는 파일이 거의 없다.

service 패키지에 SchedulerService라는 파일을 생성했다. 내용은 아래와 같다.

package com.tistory.in0pro.service; import org.springframework.stereotype.Service; @Service public class SchedulerService { public void scheduleRun(){ System.out.println(“여기에 로직을 넣으면 된다.”); } }

어디에 자리를 만들어도 상관 없지만

비즈니스 로직은 대부분 service 영역에서 처리하고 , 스케쥴러는 개수가 늘어날 수 있기 때문에

스케쥴러 전용 service를 따로 만들었다.

이제 자리는 마련이 되었고, spring에 스케쥴러 세팅을 하러 가자.

2. root-context.xml 파일을 연다.

회사 프로젝트에선 root-context가 없었는데, 이럴 경우 대충 비슷한 파일을 찾아주자.

(base-context, context-root 등…)

이때, 파일이 어디 있는지 모르겠다면 ctrl+shift+R 을 누르고 *context를 검색하자. (아래 이미지 참고)

아무것도 건드리지 않은 프로젝트라면 아래와 비슷한 상태일 것이다.

3. root-context에 cron 세팅 코드를 넣어주자.

빨간색 괄호는 스케쥴링을 위해 새로 추가한 부분이다

(복사하기 편하게 코드 블록에 한번 더 썼다)

class=”com.tistory.in0pro.service.SchedulerService” 부분에 아까 만들어둔 자리(파일)를 넣으면 된다.

4. 만들어둔 자리에 스케쥴러를 적용하자.

package com.tistory.in0pro.service; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @Service public class SchedulerService { @Scheduled(cron=”*/30 * * * * *”) public void scheduleRun(){ System.out.println(“성공~”); } }

이렇게 두 라인만 추가하면 된다.

cron=””에 들어갈 내용은 구글에 ‘spring cron’이라고 검색하면 잘 정리된 게시글이 많다.

참고로 “*/30 * * * * *”는 30초에 한 번씩 실행한다는 뜻이다.

나는 자동 메일링을 위해 스케쥴러를 사용했는데, 매일 아침 8시에 데이터를 처리하기 위해 cron=”0 0 8 * * *”로 돌렸다.

성공~

서버를 실행하면 잘 동작하는 것을 확인할 수 있다.

728×90

java scheduler / 자바 스케줄러 예제

java scheduler / 자바 스케줄러 예제

이번엔 supinan framework 1.4.1 을 이용해서 만든 자바 스케줄러 예제입니다

지금까지 supinan framework 는 많이 썼지만 scheduler 기능은 처음 쓰는거라

아주 간단하게 만들어봤어요

이번에 만든 스케줄러 동작 조건입니다

1) 월요일만 동작한다

2) 오전 6시 5분부터 작동을 시작한다

3) 동작 등록일로부터 1년뒤까지 동작한다

(2013년 1월 8일날 등록했으면 2014년 1월 8일까지 동작)

4) 위의 조건이 만족할 때 1분 단위로 동작한다

그럼 java scheduler 의 소스 파일을 볼까요?

총 2개의 파일로 구성되어있습니다

메인 파일과 특정 조건이 되었을 때 동작하는 파일이요

우선 자바 스케줄러 2개의 예제 파일 중 하나인 메인파일입니다

우선 scheduler 객체를 생성해야겠죠?

13라인에서 해당 객체를 생성합니다

SupinanSchedule schedule = new SupinanSchedule();

그리고 종료일자 설정을 위해 16~17 라인에서

현재 날짜에 1년 뒤를 설저해놓습니다

마지막으로 20번째줄부터 스케줄러 동작 조건대로

설정값을 넣어 스케줄을 등록합니다

첫번째 파라메터 = 조건 만족시 동작할 scheduler 구현체

두번째 파라메터 = 동작 요일을 배열로 설정 (조건에 맞게 월요일만 설정함)

세번째 파라메터 = 동작 시작 시간 (6시부터 동작하도록 설정)

네번째 파라메터 = 동작 시작 분 (6시 5분부터 동작하도록 설정)

다섯번째 파라메터 = 현재 시간으로 설정

여섯번째 파라메터 = 16라인에서 설정한 현재의 1년 뒤 시간 설정

schedule.addSchedule(…) 이 메소드가 수십가지가 되는데

그 중 제가 사용한건 하나고요

특정 요일만, 특정 날짜만, 특저요일에 특정 횟수만 등등

여러가지 스케줄러 기법을 제공합니다

등록한 java scheduler 의 조건이 만족했을 때 호출되는 구현체입니다

기본적으로 인터페이스인 comsupinan.schedule.Schedule 를 구현해야합니다

그럼 2개의 메소드가 필요한데 각각 아래와 같네요

public void destroy() = 사용자가 scheudle.removeSchedule(long id) 를 호출했을 때와

지정한 종료조건이 만족해서 스케줄러가 삭제될 때 호출됩니다

public void execute() = java scheduler 동작 조건이 될 떄 호출됩니다

처음에 destroy() 는 무조건 한번 호출되거나 무한으로 반복하게했으면

아예 호출 안될수도 있고

execute() 는 하루도 여러번 호출되거나 아예 안될수도 있죠

제가 이클립스로 javs scheduler 예제 파일을 만들어서

이클립스 상에서 캡쳐한 폴더 구조입니다

여기는 안나와있는데 저는 supinan framework 에서 제공하는

유틸리티 중 하나인 자바 스케줄러를 이용한거라서

당연히 supinan1.4.1.jar 파일을 임포트해야해요

이건 첨부파일에도 있으니까 참고하시고

직접 받으실려만 supinan framework 사이트에서 받으세요

사이트는 검색사이트에서 수피난 검색하면 나오고

그 사이트 오른쪽 상단에보면 녹색글씨로 supinan frmaework 라는

링크가 보일거예요. 그걸 눌러주셔야해요

이 사이트가 java scheduler 예제를 구현하기 위해 사용한

supinan framework 공식 사이트입니다

첫 화면 모습이예요

왼쪽 메뉴에 빨간 동그라미 보이죠??

그걸 누르시면 다운로드 화면으로 이동해요

여기가 자바 스케줄러 구현을 위해 사용한 supinan framwork 를 받을 수 있는 곳인데요

빨간 동그라미에 다운로드 써있는걸 누르시면 라이브러리를 받아서

사용할 수 있습니다

귀찮게 사이트 안들어가셔도 첨부한 파일에 java scheduler 예제 java 파일하고

framework jar 파일 첨부했으니까 그거 쓰셔도 됩니다

편하신 방법으로 해보세요

[JAVA] @Scheduled – 스케줄러 사용법

728×90

반응형

이번에 프로젝트를 하면서 다음과 같은 문제가 생겼다.

어떤 사용자에게 권한이 있는데, 이 사용자의 부서가 이동 되었을 때 해당 권한을 제거해줘야 하는 메서드를 만들었는데,

그냥 update를 날리는 단순한 쿼리만 돌리면 되서, 어느 지점에서 해당 메서드를 호출할 것인가? 가 문제였다.

처음에는 사용자가 로그인할때마다 체크해서 권한을 제거하는 방식으로 구현하였지만..

부서이동은 그렇게 자주 일어나는 이벤트가 아니므로, 하루나 일주일에 한번씩 돌리는게 낫지 않겠냐? 고 하여

스케줄러를 이용하여 구현 하는 김에 스케줄러를 정리한다.

@Scheduled

주기적인 작업이 있을 때 @Scheduled 어노테이션을 사용하면 쉽게 적용이 가능하다. 사용방법은 다음과 같다.

테스트용 클래스/메서드

위와 같이 현재시간을 찍어 주는 메서드를 만들었다. 이제 간단히 관련 어노테이션을 붙여주면

스케줄러가 돌 것이다.

해당 메서드는 5초마다 현재시간을 콘솔에 찍어주는 메서드이다.

간단히 @EnableScheduling을 클래스에 붙여서 여기서 스케줄러를 사용하겠다! 라고 알려주고,

주기적으로 실행 할 메서드에 @Scheduled를 붙여주어 몇초마다 해당 메서드를 실행할 건지 옵션값을 주면 된다.

또한 클래스에 @Component, @Controller나 @Service 등을 적어주어야 하며 그럼 아래와 같이 된다.

실행 화면

5초마다 콘솔에 현재시간을 찍고 있다. 그런데 2번씩 찍힌다.. 이게 왜 그런가 하고 찾아보니..

Spring 설정의 경우 @Component 어노테이션이 등록이 되어 있는 상태에서 context-scan이 되면 bean이 두번 선언되어 중복 실행되는 경우도 있다고 한다. -> @Component를 @Controller으로 수정 하니 해결 되었다!

@Scheduled의 옵션값에 들어가는 cron은 구글에 검색하면 자세히 나오니 참고하면 될 거 같다.

728×90

반응형

[JAVA] 스케줄러(Quartz) 실행하는 법

728×90

반응형

스케줄러란?

일정주기마다 특정 작업을 실행시키는 기능

일정한 시간, 일정한 주기마다 DB를 조회하거나 API 호출하는 등 작업을 실행해야 하는 경우가 있다. JAVA에서는 Quartz라는 lib을 이용해서 스케줄러를 구현할 수 있다. 메인메소드를 통해 일정한 주기로 작업을 실행하는 스케줄러를 만들어보겠다.

– SampleJobExecutor.java (Job 인터페이스 상속)

package com.odumak.quartz; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class SampleJobExecutor implements Job { private static final SimpleDateFormat TIMESTAMP_FMT = new SimpleDateFormat(“yyyy-MM-dd hh:mm:ss.SSSS”); public static final String EXECUTION_COUNT = “EXECUTION_COUNT”; @Override public void execute(JobExecutionContext ctx) throws JobExecutionException { JobDataMap map = ctx.getJobDetail().getJobDataMap(); String currentDate = TIMESTAMP_FMT.format(new Date()); String message = map.getString(“message”); int executeCount = 0; if (map.containsKey(EXECUTION_COUNT)) { executeCount = map.getInt(EXECUTION_COUNT); } executeCount += 1; map.put(EXECUTION_COUNT, executeCount); System.out.println(String.format(“[%-18s][%d][%s] %s”, “execute”, executeCount, currentDate, message )); } }

– MyJobListner.java

package com.odumak.quartz; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobListener; public class MyJobListener implements JobListener { @Override public String getName() { return MyJobListener.class.getName(); } /** * Job이 수행되기 전 상태 * – TriggerListener.vetoJobExecution == false */ @Override public void jobToBeExecuted(JobExecutionContext context) { System.out.println(String.format(“[%-18s][%s] 작업시작”, “jobToBeExecuted”, context.getJobDetail().getKey().toString())); } /** * Job이 중단된 상태 * – TriggerListener.vetoJobExecution == true */ @Override public void jobExecutionVetoed(JobExecutionContext context) { System.out.println(String.format(“[%-18s][%s] 작업중단”, “jobExecutionVetoed”, context.getJobDetail().getKey().toString())); } /** * Job 수행이 완료된 상태 */ @Override public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) { System.out.println(String.format(“[%-18s][%s] 작업완료”, “jobWasExecuted”, context.getJobDetail().getKey().toString())); } }

– MyTriggerListner.java

package com.odumak.quartz; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.Trigger; import org.quartz.Trigger.CompletedExecutionInstruction; import org.quartz.TriggerListener; public class MyTriggerListener implements TriggerListener { public static final String EXECUTION_COUNT = “EXECUTION_COUNT”; public String getName() { return MyTriggerListener.class.getName(); } /** * Trigger가 실행된 상태 * 리스너 중에서 가장 먼저 실행됨 */ public void triggerFired(Trigger trigger, JobExecutionContext context) { System.out.println(String.format(”

[%-18s][%s]”, “triggerFired”, trigger.getKey().toString())); } /** * Trigger 중단 여부를 확인하는 메소드 * Job을 수행하기 전 상태 * * 반환값이 false인 경우, Job 수행 * 반환값이 true인 경우, Job을 수행하지않고 ‘SchedulerListtener.jobExecutionVetoed’로 넘어감 * * Job 실행횟수가 3회이상이면 작업중단 */ public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) { JobDataMap map = context.getJobDetail().getJobDataMap(); int executeCount = -1; if (map.containsKey(EXECUTION_COUNT)) { executeCount = map.getInt(EXECUTION_COUNT); } System.out.println(String.format(“[%-18s][%s]”, “vetoJobExecution”, trigger.getKey().toString())); return executeCount >= 3; } /** * Trigger가 중단된 상태 */ public void triggerMisfired(Trigger trigger) { System.out.println(String.format(“[%-18s][%s]”, “triggerMisfired”, trigger.getKey().toString())); } /** * Trigger가 완료된 상태 */ public void triggerComplete(Trigger trigger, JobExecutionContext context, CompletedExecutionInstruction triggerInstructionCode) { System.out.println(String.format(“[%-18s][%s]”, “triggerComplete”, trigger.getKey().toString())); } }

– JobLuacher.java

package com.odumak.quartz; import org.quartz.Job; import org.quartz.JobBuilder; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.ListenerManager; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.SimpleTrigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; public class JobLuacher { public static void main(String[] args) { try { // Scheduler 생성 SchedulerFactory factory = new StdSchedulerFactory(); Scheduler scheduler = factory.getScheduler(); // Listener 설정 ListenerManager listenrManager = scheduler.getListenerManager(); listenrManager.addJobListener(new MyJobListener()); listenrManager.addTriggerListener(new MyTriggerListener()); // Scheduler 실행 scheduler.start(); // JOB Executor Class Class jobClass = SampleJobExecutor.class; // JOB Data 객체 생성 JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put(“message”, “Hello, Quartz!!!”); jobDataMap.put(SampleJobExecutor.EXECUTION_COUNT, 0); // JOB 생성 JobDetail jobDetail = JobBuilder.newJob(jobClass) .withIdentity(“job_name”, “job_group”) .setJobData(jobDataMap) .build(); // SimpleTrigger 생성 // 5초마다 반복하며, 최대 10회 실행 SimpleScheduleBuilder simpleSch = SimpleScheduleBuilder.simpleSchedule() .withRepeatCount(10) .withIntervalInSeconds(5); SimpleTrigger simpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger() .withIdentity(“simple_trigger”, “simple_trigger_group”) .withSchedule(simpleSch) .forJob(jobDetail) .build(); // Schedule 등록 scheduler.scheduleJob(jobDetail, simpleTrigger); } catch (SchedulerException e) { e.printStackTrace(); } } }

– 결과값

728×90

반응형

ThreadPoolTaskScheduler를 이용하여 자바 스케줄러 구현 및 강제종료 구현

반응형

안녕하세요. 방구석 개발자입니다.

현재 진행중인 프로젝트에서 원하는 시간대 실행되는 배치를 등록하고 실행하는 기능을 만들어야 돼서 ThreadPoolTaskScheduler를 이용하여 구현하였는데요.

ThreadPoolTaskScheduler가 뭔지 또 어떻게 사용되는지 알아보도록 하겠습니다.

ThreadPoolTaskScheduler란

ThreadPoolTaskScheduler는 태스크실행 및 스케줄링에 사용되는 스프링 라이브러리 입니다.

배치 관리 할때 Thread를 개발자가 직접 제어하지 않고 실행하고 싶은 Task와 시간을 Pool에 넣습니다.그러면 ThreadPoolTaskScheduler에서 제어하여 해당 시간에 맞춰서 Thread를 생성 및 실행 시키고 종료 까지 해줍니다.

사용방법

SpringMVC의 경우 설정xml 파일에 다음과 같이 넣습니다. id값은 원하는 값으로 넣어주셔도 됩니다.

클래스 파일에 ThreadPoolTaskScheduler를 @Autowired 로 지정하여 변수를 만듭니다.

@Autowired private ThreadPoolTaskScheduler scheduler; private Map> jobMap=new HashMap<>();

다음 메서드 처럼 스케줄 등록및 실행 , 중지를 제어합니다.

public void exampleMethod(){ scheduler.setPoolSize(10); //스레드풀의 사이즈를 결정합니다. //스케줄러에 실행하고 싶은 Task 넣기 RunnableEx runnableEx=new RunnableEx(); ScheduledFuture scheduledFuture=scheduler.schedule(runnableEx,new CronTrigger(“0 0 12 * *”));//매일 12시(정오)에 실행되는 Task를 스케줄에 등록함. jobMap.put(“testId”,scheduledFuture); scheduler.shutdown(); //작업중인 스케줄러를 중지합니다. jobMap.remove(“testId”); }

Trigger는 Cron과 Periodic이 있어서 각각 편한쪽으로 설정하시면됩니다.

종료시 이슈 사항

이번 프로젝트에서 스케줄을 강제종료하는 기능 구현 중에 문제가 발생하여 오랜시간 애먹었습니다.

Thread는 destroy() , stop() 메소드 대신 interrupt를 일으켜 사용중지 할것을 권하고 있습니다.

자바에서 stop 메소드는 안전하지 않고 interrupt메소드 사용을 권장합니다.

그래서 ThreadPoolTaskScheduler의 shutdown() 메소드를 내부적으로 살펴보았는데요.

interruptIdleWorkers 메소드를 호출하고 거기서 Thread.interrupt()를 호출합니다. 하여 InterruptedException 처리를 해줘야 강제종료를 구현할수 있습니다.

class RunnableEx implements Runnable { @Override public void run() { try{ System.out.println(“배치 시작”); serviceLogic();//실행하고 싶은 서비스 로직 구현 System.out.println(“배치 종료”); }catch (InterruptedException e){ //배치가 강제종료되면 여기로 넘어오게됩니다. e.printStackTrace(); }finally { //do finally Logic } } }

그러나 여기에는 또 다른 함정이 있습니다. servicLogic() 부분에서 오랜 시간이 걸려 강제종료하면 종료가 되지 않았습니다. 그래서 ThreadPoolTaskScheduler의 shutdown()메소드를 살펴보았습니다.

shutdown() 메소드는 부모클래스 ExecutorConfigurationSupport 에 정의 되어 있습니다.ExecutorConfigurationSupport 의 shutdown()메소드를 따라가 보겠습니다.

See Also: ExecutorService.shutdown(), ExecutorService.shutdownNow()

ExecutorService.shutdown() 을 사용하여서 ExecutorService.shutdown()을 따라가서 주석을 보았습니다.

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical

implementations will cancel vi a Thread.interrupt ,

so any task that fails to respond to interrupts may never terminate.

능동적으로 실행 중인 작업의 처리를 중지하려는 최선의 시도 외에는 보장이 없습니다. 예를 들어 일반적인 구현은 Thread.interrupt를 통해 취소되므로 인터럽트에 응답하지 않는 작업은 절대 종료되지 않을 수 있습니다.

이 뜻은 InterruptedException처리를 하지 않으면 작업 종료가 안될수 있다는 뜻입니다.

예를 들어서 service로직에 InterruptedException 처리 하지 않은 채로 속도가 느린 쿼리를 여러번 실행 해야하고 있으면 db를 다 처리 하기 전까지 종료가 되지 않습니다.

public void serviceLogic() { //do service for(int i=0;i<10;i++){ selectDb(); updateDb(); insertLog(); }// 강제종료가 되지 않고 계속 실행됨 } public void updateDb(){ //updateDB } public void selectDb(){ //selectDB } public void insertLog(){ //insertDB } 해당부분은 강제종료시에 boolean값으로 트리거 시켜서 InterruptedException을 던져주어 해결하였습니다. private boolean shutDown=false; public void isStop(){ scheduler.shutdown(); //작업중인 스케줄러를 중지합니다. shutDown=true; // InterruptedException를 일으키는 boolean } public void serviceLogic() throws InterruptedException { //do service for(int i=0;i<10;i++){ if(shutDown) throw new InterruptedException(); selectDb(); updateDb(); insertLog(); } } public void updateDb(){ //updateDB } public void selectDb(){ //selectDB } public void insertLog(){ //insertDB } 정리 ThreadPoolTashkScheduler 를 종료시에는 서비스로직에서 InterruptedException처리를 해주어야 종료될수 있습니다. 회사에서 며칠을 고생해서 구현 한거라서 정리해보았습니다. 최대한 잘 설명을 하려고 하였으나 두서없이 적은거 같습니다.. ㅜㅜ 다음에 다시 한 번 정리해보도록 하겠습니다. 감사합니다. 반응형

Java에서 주기적으로 작업 실행

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

import com . google . common . util . concurrent . AbstractScheduledService ; import java . util . Date ; import java . util . concurrent . TimeUnit ; class ScheduledExecutor extends AbstractScheduledService { @Override protected void startUp ( ) { System . out . println ( “Job started at: ” + new java . util . Date ( ) ) ; } @Override protected void runOneIteration ( ) throws Exception { System . out . println ( “Running: ” + new java . util . Date ( ) ) ; } @Override protected Scheduler scheduler ( ) { // 1초마다 실행 return Scheduler . newFixedRateSchedule ( 0 , 1 , TimeUnit . SECONDS ) ; } @Override protected void shutDown ( ) { System . out . println ( “Job terminated at: ” + new java . util . Date ( ) ) ; } } class Main { public static void main ( String [ ] args ) throws InterruptedException { ScheduledExecutor executor = new ScheduledExecutor ( ) ; executor . startAsync ( ) ; Thread . sleep ( 10000 ) ; executor . stopAsync ( ) ; } }

Java Quartz Scheduler – Job Chaining 구현

Java Quartz Scheduler – Job Chaining 구현

Java로 Job Scheduling을 쉽게(참 조심스러운 단어.. ㅋㅋ) 할 수 있게 해주는 쿼츠(Quartz) 스케줄러가 있다.

이 사이트에 나와있는 문서들은 여태 본 기술 사이트 문서 중에 가장 맘에 드는 스타일로 구성되어 있다. 길지 않은 설명, 간략하면서도 필요한 정보를 모두 담고 있는 다양한 기본 예제와 실무형 Cookbook까지 정말 마음에 쏙 든다. 게다가 스프링부트 스타터로도 제공되므로 더욱 편리하게 프로젝트에서 사용할 수 있다.

그런데 옥의 티랄까.. 독립적인 Job은 훌륭한 문서와 쉬운 Fluent API 덕에 간단하게 구현할 수 있는데, 연속적인 Job 실행은 간단하게 구현할 수 있는 방법이 없는 것 같다. 그래서 검색을 해보니 결국에는 Job 실행에 사용되는 Context 객체 안에 다음에 실행할 Job을 넣어주고 스케줄링하는 방식으로 연속적인 Job 실행을 구현할 수 있다.

그래서 간단하면서도 용도에 맞게 조금만 확장하면 아주 쓸만한 구현 예제를 만들어 봤다. 전체 코드는 https://github.com/HomoEfficio/quartz-scratchpad 에 있다.

Quartz 기초 개념

쿼츠에 대한 감을 잡는 데는 단 한 줄이면 충분하다.

1

scheduler.scheduleJob(jobDetail, trigger);

jobDetail 에는 Job의 실제 구현 내용과 Job 실행에 필요한 제반 상세 정보가 담겨 있다.

에는 Job의 실제 구현 내용과 Job 실행에 필요한 제반 상세 정보가 담겨 있다. trigger 에는 Job을 언제, 어떤 주기로, 언제부터 언제까지 실행할지에 대한 정보가 담겨 있다.

에는 Job을 언제, 어떤 주기로, 언제부터 언제까지 실행할지에 대한 정보가 담겨 있다. scheduler는 jobDetail 과 trigger 에 담긴 정보를 이용해서 실제 Job의 실행 스케줄링을 담당한다.

Quartz 기초 예제

쿼츠 스케줄링을 통해 로그를 찍는 간단한 예제를 살펴보자.

HelloJob

단순히 로그를 찍는 Job

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

package io.homo.efficio.scratchpad.quartz;

import lombok.extern.slf4j.Slf4j;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

4j

public class HelloJob implements Job {

public void execute (JobExecutionContext context) throws JobExecutionException {

log.info( “### Hello Job is being executed!” );

}

}

QuartzTest

HelloJob을 스케줄링하고 실행하는 테스트. 물론 public static void main() 으로 해도 무방하다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

package io.homo.efficio.scratchpad.quartz;

import org.junit.Test;

import org.quartz.JobDetail;

import org.quartz.Scheduler;

import org.quartz.SchedulerException;

import org.quartz.Trigger;

import org.quartz.impl.StdSchedulerFactory;

import static org.quartz.JobBuilder.newJob;

import static org.quartz.TriggerBuilder.newTrigger;

public class QuartzTest {

public void helloJob () throws SchedulerException, InterruptedException {

JobDetail jobDetail = newJob(HelloJob.class)

.build();

Trigger trigger = newTrigger()

.build();

Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler();

defaultScheduler.start();

defaultScheduler.scheduleJob(jobDetail, trigger);

Thread.sleep( 3 * 1000 );

defaultScheduler.shutdown( true );

}

}

테스트 결과

다음과 같이 HelloJob에 구현된 로그 출력이 성공적으로 수행된다.

1

2

3

00:53:15.137 [DefaultQuartzScheduler_Worker-1] INFO io.homo.efficio.scratchpad.quartz.HelloJob – ### Hello Job is being executed!

Job Chaining 기본 틀 구현

이제 위의 간단한 HelloJob을 넘어서 Job을 연속적으로 실행할 수 있는 Job Chaining을 구현해보자.

연속 실행 기능을 가질 추상 클래스인 BaseJob 을 만들고, 실제 구현 내용을 담은 HelloJob은 BaseJob 을 상속하게 만든다.

BaseJob

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

package io.homo.efficio.scratchpad.quartz;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

public abstract class BaseJob implements Job {

public void execute (JobExecutionContext context) throws JobExecutionException {

doExecute(context);

}

protected abstract void doExecute (JobExecutionContext context) ;

}

HelloJob

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

package io.homo.efficio.scratchpad.quartz;

import lombok.extern.slf4j.Slf4j;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

4j

public class HelloJob extends BaseJob {

protected void doExecute (JobExecutionContext context) {

log.info( “### Hello Job is being executed!” );

}

}

테스트 재실행

테스트 코드는 바꿀 필요 없다. 실행해보면 전과 마찬가지로 로그가 성공적으로 출력된다.

1

2

3

01:22:41.393 [DefaultQuartzScheduler_Worker-1] INFO io.homo.efficio.scratchpad.quartz.HelloJob – ### Hello Job is being executed!

템플릿 메서드 패턴 적용

BaseJob 에 템플릿 메서드 패턴을 적용해서 Job 실행 전처리 , Job 실행 , 후처리 , 다음 Job Scheduling 이라는 파이프라인을 구성한다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

package io.homo.efficio.scratchpad.quartz;

import lombok.extern.slf4j.Slf4j;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

4j

public abstract class BaseJob implements Job {

public void execute (JobExecutionContext context) throws JobExecutionException {

beforeExecute(context);

doExecute(context);

afterExecute(context);

scheduleNextJob(context);

}

private void beforeExecute (JobExecutionContext context) {

log.info( “%%% Before executing job” );

}

protected abstract void doExecute (JobExecutionContext context) ;

private void afterExecute (JobExecutionContext context) {

log.info( “%%% After executing job” );

}

private void scheduleNextJob (JobExecutionContext context) {

log.info( “$$$ Schedule Next Job” );

}

}

테스트 재실행

테스트를 재실행해보면 다음과 같이 전처리 , Job 실행 , 후처리 , 다음 Job 스케줄링 이 실행됨을 알 수 있다.

1

2

3

4

5

6

01 : 41 : 16.254 [DefaultQuartzScheduler_Worker- 1 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% Before executing job

01:41:16.254 [DefaultQuartzScheduler_Worker-1] INFO io.homo.efficio.scratchpad.quartz.HelloJob – ### Hello Job is being executed!

01 : 41 : 16.254 [DefaultQuartzScheduler_Worker- 1 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% After executing job

01 : 41 : 16.254 [DefaultQuartzScheduler_Worker- 1 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – $$$ Schedule Next Job

Job Chaining 실제 구현

여기에서는 쿼츠에 대한 부연 설명이 조금 필요하다.

execute() 메서드에 넘겨지는 JobExecutionContext 에는 Job 실행에 필요한 다양한 정보를 담을 수 있다. 그 중에서도 JobDataMap 을 이용하면 자유롭게 Key-Value 데이터를 담을 수 있다. 다음과 같이 테스트 코드를 바꿔서 정보를 담아보자.

1

2

3

4

5

6

7

8

9

10

11

12

13

public void helloJob () throws SchedulerException, InterruptedException {

JobDataMap jobDataMap = new JobDataMap();

jobDataMap.put( “JobName” , “Job Chain 1” );

JobDetail jobDetail = newJob(HelloJob.class)

.usingJobData(jobDataMap)

.build();

… 이하 생략 …

그리고 HelloJob 클래스도 JobDataMap 에 담긴 정보를 사용하도록 바꿔보자.

1

2

3

4

5

6

7

8

9

4j

public class HelloJob extends BaseJob {

protected void doExecute (JobExecutionContext context) {

log.info( “### {} is being executed!” ,

context.getJobDetail().getJobDataMap().get( “JobName” ).toString());

}

}

테스트를 재실행하면 다음과 같이 JobDataMap 에 담은 정보가 함께 출력된다.

1

2

3

4

01 : 57 : 06.889 [DefaultQuartzScheduler_Worker- 1 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% Before executing job

01:57:06.889 [DefaultQuartzScheduler_Worker-1] INFO io.homo.efficio.scratchpad.quartz.HelloJob – ### Job Chain 1 is being executed!

01 : 57 : 06.891 [DefaultQuartzScheduler_Worker- 1 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% After executing job

01 : 57 : 06.891 [DefaultQuartzScheduler_Worker- 1 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – $$$ Schedule Next Job

이제 JobDataMap 에 다음 Job에 대한 정보를 담으면 Job Chaining을 할 수 있을 것 같다.

Chaining 기본 아이디어

Job과 JobDataMap은 일대일 관계이므로,

Chaining 할 모든 Job 정보를 큐에 담고,

그 큐를 처음 실행되는 Job의 JobDataMap 에 담은 후에,

에 담은 후에, Job 실행이 완료되면 후처리 단계에서 실행이 완료된 Job을 큐에서 하나씩 빼주고,

다음 Job을 실행할 때 그 큐를 다음 Job의 JobDataMap 에 넣어주고 스케줄링

에 넣어주고 스케줄링 큐가 비워지면 Chaining은 종료된다.

Chaining 할 여러 Job 생성

Job 3개를 Chaining해서 실행할 수 있도록 테스트 코드를 변경한다.

예제에서는 편의상 3개의 Job에 모두 HelloJob.class 만을 사용했지만, 실제로는 서로 다른 클래스를 사용해도 무방하다. 또한 JobBuilder API를 참고하면 Job마다 원하는 대로 식별자를 줄 수도 있고 오류 시 재실행 옵션 등 다양하게 설정할 수 있다. TriggerBuilder API를 참고하면 Trigger 도 원하는 대로 더 다양하게 구성할 수 있다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

public class QuartzTest {

public void helloJob () throws SchedulerException, InterruptedException {

JobDataMap jobDataMap1 = new JobDataMap();

jobDataMap1.put( “JobName” , “Job Chain 1” );

JobDetail jobDetail1 = newJob(HelloJob.class)

.usingJobData(jobDataMap1)

.build();

JobDataMap jobDataMap2 = new JobDataMap();

jobDataMap2.put( “JobName” , “Job Chain 2” );

JobDetail jobDetail2 = newJob(HelloJob.class)

.usingJobData(jobDataMap2)

.build();

JobDataMap jobDataMap3 = new JobDataMap();

jobDataMap3.put( “JobName” , “Job Chain 3” );

JobDetail jobDetail3 = newJob(HelloJob.class)

.usingJobData(jobDataMap3)

.build();

Job 정보를 JobDataMap에 저장

실행할 모든 Job의 JobDetail 를 첫 번째 JobDetail 의 JobDataMap 에 담는다.

1

2

3

4

5

6

7

8

9

List jobDetailQueue = new LinkedList<>();

jobDetailQueue.add(jobDetail1);

jobDetailQueue.add(jobDetail2);

jobDetailQueue.add(jobDetail3);

jobDetail1.getJobDataMap().put( “JobDetailQueue” , jobDetailQueue);

테스트 코드의 나머지 부분은 변경할 것이 없다.

나머지는 BaseJob 에서 처리한다.

후처리 단계에서 완료된 Job을 큐에서 제거

BaseJob 의 후처리 메서드인 afterExecute() 를 다음과 같이 작성해서 큐에서 완료된 Job을 제거한다.

1

2

3

4

5

6

7

8

9

private void afterExecute (JobExecutionContext context) {

log.info( “%%% After executing job” );

Object object = context.getJobDetail().getJobDataMap().get( “JobDetailQueue” );

List jobDetailQueue = (List) object;

if (jobDetailQueue.size() > 0 ) {

jobDetailQueue.remove( 0 );

}

}

다음 Job 스케줄링

scheduleNextJob() 메서드를 다음과 같이 변경해서, 완료된 Job이 제거된 큐를 JobDataMap 에 담고 즉시 실행하는 Trigger 를 만들어서 스케줄링 한다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

private void scheduleNextJob (JobExecutionContext context) {

log.info( “$$$ Schedule Next Job” );

Object object = context.getJobDetail().getJobDataMap().get( “JobDetailQueue” );

List jobDetailQueue = (List) object;

if (jobDetailQueue.size() > 0 ) {

JobDetail nextJobDetail = jobDetailQueue.get( 0 );

nextJobDetail.getJobDataMap().put( “JobDetailQueue” , jobDetailQueue);

Trigger nowTrigger = newTrigger().startNow().build();

try {

Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

scheduler.start();

scheduler.scheduleJob(nextJobDetail, nowTrigger);

} catch (SchedulerException e) {

throw new RuntimeException(e);

}

}

}

테스트 재실행

다음과 같이 Job 1, 2, 3이 모두 연속적으로 실행되는 것을 확인할 수 있다. 각 Job마다 서로 다른 워커 스레드에서 실행되는 것도 확인할 수 있다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

02 : 33 : 47.650 [DefaultQuartzScheduler_Worker- 1 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% Before executing job

02:33:47.650 [DefaultQuartzScheduler_Worker-1] INFO io.homo.efficio.scratchpad.quartz.HelloJob – ### Job Chain 1 is being executed!

02 : 33 : 47.651 [DefaultQuartzScheduler_Worker- 1 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% After executing job

02 : 33 : 47.652 [DefaultQuartzScheduler_Worker- 1 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – $$$ Schedule Next Job

02 : 33 : 47.655 [DefaultQuartzScheduler_Worker- 2 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% Before executing job

02:33:47.656 [DefaultQuartzScheduler_Worker-2] INFO io.homo.efficio.scratchpad.quartz.HelloJob – ### Job Chain 2 is being executed!

02 : 33 : 47.656 [DefaultQuartzScheduler_Worker- 2 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% After executing job

02 : 33 : 47.656 [DefaultQuartzScheduler_Worker- 2 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – $$$ Schedule Next Job

02 : 33 : 47.658 [DefaultQuartzScheduler_Worker- 3 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% Before executing job

02:33:47.658 [DefaultQuartzScheduler_Worker-3] INFO io.homo.efficio.scratchpad.quartz.HelloJob – ### Job Chain 3 is being executed!

02 : 33 : 47.658 [DefaultQuartzScheduler_Worker- 3 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – %%% After executing job

02 : 33 : 47.659 [DefaultQuartzScheduler_Worker- 3 ] INFO io.homo.efficio.scratchpad.quartz.BaseJob – $$$ Schedule Next Job

예제에서는 단순함을 위해 연속적으로 실행될 여러 Job을 관리하는 객체를 따로 만들지 않고 테스트 객체가 그 역할을 담당했지만, 실무에서는 예를 들면 Batch 같은 객체를 두고 그 안에 List 을 둬서 책임 분리를 하는 것도 좋다.

정리

키워드에 대한 정보 자바 스케줄러 구현

다음은 Bing에서 자바 스케줄러 구현 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 Node js – 스케줄러 구현

  • 자바스크립트
  • javascript
  • html
  • html5
  • 웹개발
  • 기초
  • 웹개발기초
  • 자바스크립트 기초
  • html 기초
  • 자바스크립트 팁
  • css
  • vue.js
  • react
  • react.js
  • angular
  • 안드로이드
  • ios
  • 제주도
  • 디지털노마드
  • 소프트웨어
  • schdeule
  • 스케줄러
  • node.js
  • 노드
  • node js

Node #js # #- #스케줄러 #구현


YouTube에서 자바 스케줄러 구현 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 Node js – 스케줄러 구현 | 자바 스케줄러 구현, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.

See also  제주 굿모닝 호 | 제주 굿모닝호 한치낚시 상위 58개 답변

Leave a Reply

Your email address will not be published. Required fields are marked *