java 定时调用api_Java定时器的使用 Java API 的&Quartz

Java API中的定时器

1. 创建Maven项目 暂时不添加依赖

2.创建MyQuartz继承TimerTask类

package cn.icanci.myquartz;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.TimerTask;

/**

* @Author: icanci

* @ProjectName: quartz

* @PackageName: cn.icanci.myquartz

* @Date: Created in 2020/2/14 16:17

* @ClassAction: 定时器的基本使用

*/

public class MyQuartz extends TimerTask {

@Override

public void run() {

for (int i = 0; i < 10; i++){

System.out.print(i +" ");

}

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String format = sdf.format(new Date());

System.out.println(format);

}

}

3.测试自己的定时器

package cn.icanci.myquartz;

import java.util.Timer;

/**

* @Author: icanci

* @ProjectName: quartz

* @PackageName: cn.icanci.myquartz

* @Date: Created in 2020/2/21 10:16

* @ClassAction: 测试

*/

public class TimeTest extends Timer {

public static void main(String[] args) {

Timer timer = new Timer();

MyQuartz myQuartz = new MyQuartz();

//第一个,自定义的TimerTask对象 第二个 在任务开始之后多久触发 单位 毫秒 第三个参数 每隔多久触发一次 单位 毫秒

timer.schedule(myQuartz,2000,1000);

}

}

4.Java API 实现的定时器的原理 就是实现了Runnable接口的安全线程 底层源代码使用 synchronized 修饰的代码块

public abstract class TimerTask implements Runnable {

final Object lock = new Object();

int state = VIRGIN;

static final int VIRGIN = 0;

static final int SCHEDULED = 1;

static final int EXECUTED = 2;

static final int CANCELLED = 3;

long nextExecutionTime;

long period = 0;

protected TimerTask() {

}

public abstract void run();

public boolean cancel() {

synchronized(lock) {

boolean result = (state == SCHEDULED);

state = CANCELLED;

return result;

}

}

public long scheduledExecutionTime() {

synchronized(lock) {

return (period < 0 ? nextExecutionTime + period

: nextExecutionTime - period);

}

}

}

Timer类

public class Timer {

private final TaskQueue queue = new TaskQueue();

private final TimerThread thread = new TimerThread(queue);

public Timer() {

this("Timer-" + serialNumber());

}

public Timer(boolean isDaemon) {

this("Timer-" + serialNumber(), isDaemon);

}

public Timer(String name) {

thread.setName(name);

thread.start();

}

public Timer(String name, boolean isDaemon) {

thread.setName(name);

thread.setDaemon(isDaemon);

thread.start();

}

public void schedule(TimerTask task, long delay) {

if (delay < 0)

throw new IllegalArgumentException("Negative delay.");

sched(task, System.currentTimeMillis()+delay, 0);

}

private void sched(TimerTask task, long time, long period) {

if (time < 0)

throw new IllegalArgumentException("Illegal execution time.");

// Constrain value of period sufficiently to prevent numeric

// overflow while still being effectively infinitely large.

if (Math.abs(period) > (Long.MAX_VALUE >> 1))

period >>= 1;

synchronized(queue) {

if (!thread.newTasksMayBeScheduled)

throw new IllegalStateException("Timer already cancelled.");

synchronized(task.lock) {

if (task.state != TimerTask.VIRGIN)

throw new IllegalStateException(

"Task already scheduled or cancelled");

task.nextExecutionTime = time;

task.period = period;

task.state = TimerTask.SCHEDULED;

}

queue.add(task);

if (queue.getMin() == task)

queue.notify();

}

}

}

class TaskQueue {

private TimerTask[] queue = new TimerTask[128];

private int size = 0;

int size() {

return size;

}

void add(TimerTask task) {

// Grow backing store if necessary

if (size + 1 == queue.length)

queue = Arrays.copyOf(queue, 2*queue.length);

queue[++size] = task;

fixUp(size);

}

TimerTask getMin() {

return queue[1];

}

TimerTask get(int i) {

return queue[i];

}

void removeMin() {

queue[1] = queue[size];

queue[size--] = null; // Drop extra reference to prevent memory leak

fixDown(1);

}

void quickRemove(int i) {

assert i <= size;

queue[i] = queue[size];

queue[size--] = null; // Drop extra ref to prevent memory leak

}

void rescheduleMin(long newTime) {

queue[1].nextExecutionTime = newTime;

fixDown(1);

}

boolean isEmpty() {

return size==0;

}

void clear() {

// Null out task references to prevent memory leak

for (int i=1; i<=size; i++)

queue[i] = null;

size = 0;

}

private void fixUp(int k) {

while (k > 1) {

int j = k >> 1;

if (queue[j].nextExecutionTime <= queue[k].nextExecutionTime)

break;

TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;

k = j;

}

}

private void fixDown(int k) {

int j;

while ((j = k << 1) <= size && j > 0) {

if (j < size &&

queue[j].nextExecutionTime > queue[j+1].nextExecutionTime)

j++; // j indexes smallest kid

if (queue[k].nextExecutionTime <= queue[j].nextExecutionTime)

break;

TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;

k = j;

}

}

void heapify() {

for (int i = size/2; i >= 1; i--)

fixDown(i);

}

}

class TimerThread extends Thread {

boolean newTasksMayBeScheduled = true;

private TaskQueue queue;

TimerThread(TaskQueue queue) {

this.queue = queue;

}

public void run() {

try {

mainLoop();

} finally {

// Someone killed this Thread, behave as if Timer cancelled

synchronized(queue) {

newTasksMayBeScheduled = false;

queue.clear(); // Eliminate obsolete references

}

}

}

/**

* The main timer loop. (See class comment.)

*/

private void mainLoop() {

while (true) {

try {

TimerTask task;

boolean taskFired;

synchronized(queue) {

// Wait for queue to become non-empty

while (queue.isEmpty() && newTasksMayBeScheduled)

queue.wait();

if (queue.isEmpty())

break; // Queue is empty and will forever remain; die

// Queue nonempty; look at first evt and do the right thing

long currentTime, executionTime;

task = queue.getMin();

synchronized(task.lock) {

if (task.state == TimerTask.CANCELLED) {

queue.removeMin();

continue; // No action required, poll queue again

}

currentTime = System.currentTimeMillis();

executionTime = task.nextExecutionTime;

if (taskFired = (executionTime<=currentTime)) {

if (task.period == 0) { // Non-repeating, remove

queue.removeMin();

task.state = TimerTask.EXECUTED;

} else { // Repeating task, reschedule

queue.rescheduleMin(

task.period<0 ? currentTime - task.period

: executionTime + task.period);

}

}

}

if (!taskFired) // Task hasn't yet fired; wait

queue.wait(executionTime - currentTime);

}

if (taskFired) // Task fired; run it, holding no locks

task.run();

} catch(InterruptedException e) {

}

}

}

}

在Timer类中还有另外俩类,TaskQueue和TimerThread

TaskQueue是一个队列,初始队列高度为 128 此队列是为了存储 定时任务的,使用 synchronized 修饰 是线程安全的

TimerThread 是定时任务的启动线程 是用来启动定时任务线程的 使用 synchronized 修饰 是线程安全的

定时器本质就是线程

Quartz是和Spring框架一起使用的,所以需要添加以下依赖

org.quartz-scheduler

quartz

2.3.0

org.springframework

spring-context-support

5.0.2.RELEASE

1.Quartz核心架构

Scheduler 核心调度器

Job 任务

JobDetail 任务描述

Tigger 触发器

196299148768

Quartz

定义Job和JobDetail

定义Trigger和上面的Job一起注册到Scheduler中

Scheduler通过Trigger执行Job

2.使用方法

2.1

创建一个Java类,创建一个普通方法,作为任务处理方法

2.2

配置Job到Spring容器

2.3

将Job类配置到JobDetail

execute

2.4

配置任务调度触发器

2.5

配置调度工厂

Cron表达式

Cron表达式被用来配置CornTiggger实例,Cron的表达式是字符串,实际上是 七子表达式,描述个别细节时间的时间表.这些子表达式是分开的空白代表

1.Sceonds

2.Minutes

3.Hours

4.Day-of-Month

5.Month

6.Day-of-Week

7.Year (可选字段)

例子: "0 0 12 ? * WED" 在每星期三12点执行

测试类

package cn.icanci.springquartz.schedule;

/**

* @Author: icanci

* @ProjectName: quartz

* @PackageName: cn.icanci.springquartz.schedule

* @Date: Created in 2020/2/22 12:59

* @ClassAction: 任务调度测试

*/

public class Schedule {

public void execute(){

//0/5 * * * * ? 5秒执行一次

System.out.println("Schedule.execute");

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值