常⽤的⼏种定时任务详解
常⽤的⼏种定时任务详解
李楠篮球训练营⼀、实现定时任务的⽅案
1 、使⽤Thread.sleep(1000)
2 、使⽤jdk的Timer和TimerTask,可以实现简单的间隔执⾏任务(在指定时间点执⾏某⼀任务,也能定时的周期性执⾏),⽆法实现按⽇历去调度执⾏任务。
3、使⽤DelayQueue队列
4、使⽤Quartz,它是⼀个异步任务调度框架,功能丰富,可以实现按⽇历调度。
5、使⽤Spring Task,Spring 3.0后提供Spring Task实现任务调度,⽀持按⽇历调度,相⽐Quartz功能稍简单,但是在开发基本够⽤,⽀持注解编程⽅式。7、分布式定时任务之XXL-JOB
⼆、Thread⽅式
public static void main(String[] args){
final int[] count ={1};
Runnable runnable =new Runnable(){
@Override
public void run(){
erad
while(true){
try{
kair kuoThread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("第 "+ count[0]+++" 次执⾏...");
}
}
};
Thread thread =new Thread(runnable);
thread.start();
}
三、Timer和TimerTask实现
Timer与TimerTask
public static void main(String[] args){
final long[] count ={0};
// TimerTask timerTask1=new TimerTask() {
/
/ @Override
// public void run() {
南京美容
// count[0]++;viscap
// System.out.println("第 " + count[0] + " 次执⾏...");
// }
// };
TimerTask timerTask2 =new TimerTask(){
@Override
public void run(){
count[0]++;
System.out.println("第 "+ count[0]+" 次执⾏...");
}
};
Timer timer =new Timer();
// 天
long delay =0;
// 秒
long period =1000;
timer.scheduleAtFixedRate(timerTask2, delay, period);
}
schedule(2 args) : 指定的计划执⾏时间 <= 当前时间,则task会被⽴即执⾏。
schedule(3 args) : 指定的计划执⾏时间 <= 当前时间,则task会被⽴即执⾏,之后按period参数固定重复执⾏。
scheduleAtFixedRate(3 args):指定的计划执⾏时间 <= 当前时间,则task会⾸先按执⾏⼀次;然后按照执⾏时间、系统当前时间和period参数计算出过期该执⾏的次数,计算按照: (当前时间 - 计划执⾏时间)/period,再次执⾏计算出的次数;最后按period参数固定重复执⾏。
schedule()⽅法更注重保持间隔时间的稳定。 scheduleAtFixedRate()⽅法更注重保持执⾏频率的稳定。
ScheduledExecutorService
阿⾥编码规约:
Timer运⾏多个TimeTask时,只要其中之⼀没有捕获抛出的异常,其它任务便会⾃动终⽌运⾏。Timer 优化⽅案,使⽤ScheduledExecutorService
ScheduledExecutorService是并发⼯具包中的类,是最理想的定时任务实现⽅式。
public static void main(String[] args){
Runnable runnable1 =new Runnable(){
@Override
public void run(){
System.out.println("Hello runnable1");
}
winpos};
Runnable runnable2 =new Runnable(){
@Override
public void run(){
System.out.println("Hello runnable2");
}
};
//⽅式⼀
//定义4个线程
ScheduledExecutorService rvice = wScheduledThreadPool(4);
/
**英文发音规则
* 参数1:实现Runnable接⼝的类
* 参数2:启动等待时间,⾸次执⾏的延时时间
* 参数3:⼀个数值,定时执⾏的间隔时间
* 参数4:与参数3对应的单位
*/
ScheduledFuture<?> scheduledFuture= rvice.scheduleAtFixedRate(runnable1,0,2, TimeUnit.SECONDS);
//⽅式⼆
ScheduledExecutorService rvice2 = wSingleThreadScheduledExecutor();
rvice2.scheduleAtFixedRate(runnable2,1,2, TimeUnit.SECONDS);
}
scheduleAtFixedRate() 按照固定频率
wimbledon
scheduleWithFixedDelay() 如果任务时间超过固定频率,按照任务实际时间延后
四、DelayQueue
DelayQueue是⼀个⽀持延时获取元素的阻塞队列, 内部采⽤优先队列PriorityQueue存储元素,同时元素必须实现Delayed 接⼝;
在创建元素时可以指定多久才可以从队列中获取当前元素,只有在延迟期满时才能从队列中提取元素。
DelayQueue属于排序队列,它的特殊之处在于队列的元素必须实现Delayed接⼝,该接⼝需要实现
you
compareTo和getDelay⽅法
getDelay⽅法:获取元素在队列中的剩余时间,只有当剩余时间为0时元素才可以出队列。
compareTo⽅法:⽤于排序,确定元素出队列的顺序。
poll():获取并移除队列的超时元素,没有则返回空。
take():获取并移除队列的超时元素,如果没有则wait当前线程,直到有元素满⾜超时条件,返回结果。
public class DelayedTask implements Delayed {
// 任务的执⾏时间
private int executeTime =0;
public DelayedTask(int delay){
Calendar calendar = Instance();
calendar.add(Calendar.SECOND, delay);
}
/**
* 元素在队列中的剩余时间
*
* @param unit
* @return
*/
@Override
public long getDelay(TimeUnit unit){
Calendar calendar = Instance();
return executeTime -(TimeInMillis()/1000);
土豆的英文}
/**
* 元素排序
*
* @param o
* @return
*/
@Override
public int compareTo(Delayed o){
long delay =Delay(TimeUnit.NANOSECONDS)- o.getDelay(TimeUnit.NANOSECONDS);
return delay ==0?0:(delay <0?-1:1);
}
public static void main(String[] args){
// 添加三个延迟任务(任务都是放在内存中)
DelayQueue<DelayedTask> queue =new DelayQueue<>();
queue.add(new DelayedTask(5));
queue.add(new DelayedTask(10));
queue.add(new DelayedTask(15));
System.out.println("start: "+ System.currentTimeMillis()/1000);
// 循环从延迟队列中拉取任务
while(queue.size()!=0){
DelayedTask delayedTask = queue.poll();
if(delayedTask !=null){
System.out.println("execute task: "+ System.currentTimeMillis()/1000);
}
//每隔2秒消费⼀次
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
五、Quartz实现
引⼊依赖