>Java >java지도 시간 >Quartz는 어떤 용도로 사용될 수 있나요?

Quartz는 어떤 용도로 사용될 수 있나요?

零下一度
零下一度원래의
2018-05-22 09:28:404609검색

쿼츠는 어떤 용도로 사용할 수 있나요?

Quartz는 작업 예약 프레임워크입니다. 예를 들어 이런 문제가 발생하면

  • 매월 25일에 신용카드 자동 상환을 받고 싶어요

  • 매년 4월 1일에 짝사랑 여신에게 익명의 축하 카드를 보내고 싶어요

  • 매시간 러브액션 영화 공부 노트를 클라우드 디스크에 백업하고 싶어요

이 질문의 요약은 다음과 같습니다: 규칙적인 시간에 뭔가를 하세요. 그리고 시간 트리거 조건은 매우 복잡할 수 있으므로(예: 매달 마지막 근무일 17시 50분) 이를 수행하려면 특별한 프레임워크가 필요할 정도로 복잡합니다. Quartz는 이런 종류의 작업을 수행하기 위해 여기에 있습니다. 트리거 조건에 대한 정의를 제공하고 해당 시점에 작업을 시작하도록 해당 작업을 트리거하는 역할을 담당합니다.

더 이상 말도 안 되는 소리는 하지 마세요. 코드는 정말 멋집니다. . .

public static void main(String[] args) {     
try { 
//创建scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//定义一个Trigger
Trigger trigger =TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") //定义name/group.startNow()//一旦加入scheduler,立即生效.
withSchedule(SimpleScheduleBuilder.simpleSchedule() //使用SimpleTrigger.withIntervalInSeconds(1) //每隔一秒执行一次.repeatForever()) //一直执行        
.build();
//定义一个JobDetail
JobDetail job =JobBuilder.newJob(HelloQuartz.class) //定义Job类为HelloQuartz类,这是真正的执行逻辑所在.withIdentity("job1", "group1") //定义name/group.usingJobData("name", "quartz") //定义属性        .build();
//加入这个调度    
scheduler.scheduleJob(job, trigger);
//启动之    
scheduler.start();
//运行一段时间后关闭 
Thread.sleep(10000);
      scheduler.shutdown(true);
   } catch (Exception e) {
    e.printStackTrace();
}

}

HelloQuartz类

public class HelloQuartz implements Job {public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetail detail = context.getJobDetail();
        String name = detail.getJobDataMap().getString("name");
        System.out.println("say hello to " + name + " at " + new Date());
    }
}

jar 패키지:

이 예에서는 Quartz의 가장 중요한 세 가지 기본 요소인

  • 스케줄러: 스케줄러를 잘 다루고 있습니다. 모든 일정은 이에 의해 제어됩니다.

  • 트리거: 트리거 조건을 정의합니다. 예제에서는 해당 유형이 SimpleTrigger이며 1초마다 실행됩니다(SimpleTrigger가 무엇인지는 아래에서 자세히 설명합니다).

  • JobDetail & Job: JobDetail은 작업 데이터를 정의하며 실제 실행 로직은 Job에 있습니다. 예에서는 HelloQuartz입니다. Job을 직접 사용하지 않고 JobDetail + Job으로 설계한 이유는 무엇인가요? Scheduler가 Job을 직접 사용하게 되면 동일한 Job 인스턴스에 동시에 접근하는 문제가 발생할 수 있기 때문이다. JobDetail & Job 메소드에서는 sheduler가 실행될 때마다 JobDetail을 기반으로 새로운 Job 인스턴스가 생성되므로 동시 접근 문제를 피할 수 있습니다.

Scheduler

Scheduler는 Quartz의 두뇌이며 모든 작업이 이에 의해 구현됩니다.

Schduelr에는 JobStore와 ThreadPool이라는 두 가지 중요한 구성 요소가 포함되어 있습니다.

JobStore는 Trigger, Scheduler, JobDetail, 비즈니스 잠금 등을 포함한 런타임 정보를 저장합니다. RAMJob(메모리 구현), JobStoreTX(JDBC, 트랜잭션은 Quartz에서 관리됨), JobStoreCMT(JDBC, 컨테이너 트랜잭션 사용), ClusteredJobStore(클러스터 구현), TerracottaJobStore(테라랙타란 무엇입니까) 등 여러 가지 구현이 있습니다.

ThreadPool은 스레드 풀이고 Quartz에는 자체 스레드 풀 구현이 있습니다. 모든 작업은 스레드 풀에 의해 실행됩니다.

SchedulerFactory

SchdulerFactory는 이름에서 알 수 있듯이 Schduler를 생성하는 데 사용됩니다. DirectSchedulerFactory와 StdSchdulerFactory의 두 가지 구현이 있습니다. 전자는 코드에서 Schduler 매개변수를 사용자 정의하는 데 사용할 수 있습니다. 후자는 Schduler를 인스턴스화하기 위해 클래스 경로 아래의 quartz.properties 구성을 직접 읽습니다(존재하지 않는 경우 기본값 사용). 일반적으로 StdSchdulerFactory를 사용하면 충분합니다.

SchdulerFactory 자체는 원격 스케줄러를 관리하는 데 사용할 수 있는 RMI 스텁 생성을 지원합니다. 기능은 로컬 기능과 동일하며 작업을 원격으로 제출할 수 있습니다.

1.job

구현 클래스 JobDetail

    JobDetail job = JobBuilder.newJob(RemindJob.class)
            .withIdentity("job1", "group1").build();//创建一个任务
     /**
      * 创建触发器
      * 第一种方式  不太好      */SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger", "myTriggerGroup").
    withSchedule(SimpleScheduleBuilder.simpleSchedule().
            withIntervalInSeconds(3).
            repeatForever()).
            startAt(new Date(System.currentTimeMillis()+1000)).build();    
    /**
     * 创建触发器
     * 第二种 方式  非常好
     * 可以 好用  2013年每月的第三个星期五上午10:30触发  0 30 10 ? * 6#3 2013
     * 2016年每月的第一个星期四下午16:17触发   0 17 16 ? * 5#1 2016
     * 每天15点到16点每5分钟运行一次,此外,每天17点到18点每5分钟运行一次  

     *//*CronTrigger trigger=TriggerBuilder.newTrigger() 
            .withIdentity("myTrigger", "myTriggerGroup")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 18 16 ? * 5#1 2016")).build();*/
    SchedulerFactory sf=new StdSchedulerFactory();//创建调度者工厂Scheduler scheduler = sf.getScheduler();//创建一个调度者scheduler.scheduleJob(job,trigger);//注册并进行调度scheduler.start();//启动调度    //Thread.sleep(millis)    //scheduler.shutdown();//关闭调度

RemindJob 类的定义

 */public class RemindJob implements Job {private RemindService service=new RemindService();
    @Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {
        service.printPlan("你好!");
        
        Date date=new Date();
        String time = date.toString();
        System.out.println(time+"job is starting");
    }

JobDetail 인스턴스를 스케줄러에 전달하는 것을 볼 수 있습니다. 왜냐하면 JobDetail을 생성할 때 작업이 수행되기 때문입니다. 실행됨 클래스 이름이 JobDetail에 전달되므로 스케줄러는 실행할 작업 유형을 알 수 있으며, 실행 후 실행(...) 메서드를 호출하기 전에 클래스의 새 인스턴스가 생성됩니다. , 인스턴스에 대한 참조가 삭제되고 인스턴스가 가비지 수집됩니다. 이 실행 전략의 한 가지 결과는 작업에 매개변수 없는 생성자가 있어야 한다는 것입니다(기본 JobFactory를 사용할 때). 또 다른 결과는 작업 클래스에서 상태 저장입니다. 데이터 속성은 여러 작업 실행 시 이러한 속성 값이 유지되지 않으므로 정의해서는 안 됩니다.

그럼 작업 인스턴스에 속성이나 구성을 추가하는 방법은 무엇입니까? 작업을 여러 번 실행하는 동안 작업 상태를 추적하는 방법은 무엇입니까? 대답은 JobDetail 개체의 일부인 JobDataMap입니다.

JobDataMap

JobDataMap은 무제한(직렬화된) 데이터 객체를 포함할 수 있으며 작업 인스턴스가 실행될 때 데이터를 사용할 수 있습니다. JobDataMap은 데이터 유형의 메소드에 쉽게 액세스하기 위한 몇 가지 추가 기본 사항이 포함된 Java Map 인터페이스의 구현입니다.

스케줄러에 작업을 추가하기 전에 JobDetail을 구축할 때 다음 예와 같이 JobDataMap에 데이터를 넣을 수 있습니다.

    JobDetail job=JobBuilder.newJob(RemindJob.class)
            .withIdentity("job1", "group1")
            .usingJobData("hello", "we are family")
            .build();

작업 실행 중에 데이터를 꺼낼 수 있습니다. 다음 예와 같이 JobDataMap의

@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {
        service.printPlan("你好!");
        JobKey key=context.getJobDetail().getKey();
        
        JobDataMap map = context.getJobDetail().getJobDataMap();
        String string = map.getString("hello");
        System.out.println(key+"==========="+string);
        
        Date date=new Date();
        String time = date.toString();
        System.out.println(time+"job is starting");
    }

如果你使用的是持久化的存储机制(本教程的JobStore部分会讲到),在决定JobDataMap中存放什么数据的时候需要小心,因为JobDataMap中存储的对象都会被序列化,因此很可能会导致类的版本不一致的问题;Java的标准类型都很安全,如果你已经有了一个类的序列化后的实例,某个时候,别人修改了该类的定义,此时你需要确保对类的修改没有破坏兼容性;更多细节,参考现实中的序列化问题。另外,你也可以配置JDBC-JobStore和JobDataMap,使得map中仅允许存储基本类型和String类型的数据,这样可以避免后续的序列化问题。

如果你在job类中,为JobDataMap中存储的数据的key增加set方法(如在上面示例中,增加setJobSays(String val)方法),那么Quartz的默认JobFactory实现在job被实例化的时候会自动调用这些set方法,这样你就不需要在execute()方法中显式地从map中取数据了。

在Job执行时,JobExecutionContext中的JobDataMap为我们提供了很多的便利。它是JobDetail中的JobDataMap和Trigger中的JobDataMap的并集,但是如果存在相同的数据,则后者会覆盖前者的值。

下面的示例,在job执行时,从JobExecutionContext中获取合并后的JobDataMap:

@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {
        service.printPlan("你好!");
        JobKey key=context.getJobDetail().getKey();        /*    JobDataMap map = context.getJobDetail().getJobDataMap();
        String string = map.getString("hello");
        System.out.println(key+"==========="+string);*/ JobDataMap map = context.getMergedJobDataMap();
         String string = map.getString("hello");
         System.out.println(key+"---------------------    "+string);

 

위 내용은 Quartz는 어떤 용도로 사용될 수 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.