调度的概念
给定时间结点,时间间隔,任务次数,然后自动执行任务
应用场景举例
日志清理:每隔三个月,清理公司日志文件
日志备份:每个一周,备份公司文件
工资结算:每个月29号,考勤汇报,业务结算,计算工资
调度的实现方式:
- Timer+TimerTask
- ScheduledExecutor
- 开源工具包:Quartz,JcronTab
单线程调度
执行调度任务的个数为单个
Timer +TimerTask实现方式:
- Timer实现
Timer是一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。
主要方法摘要
- TimerTask
方法摘要
入门案例:
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer timer = new Timer();
//任务在多久以后执行
long delay = 1000;//执行任务前的延迟时间,单位是毫秒。
long period =1000;//执行各后续任务之间的时间间隔,单位是毫秒。
timer.scheduleAtFixedRate(new Task(), delay, period);
//task - 所要安排的任务。
}
}
class Task extends TimerTask{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("正在工作");
}
}
- TaskList 和TaskThread只有一个
- Timer对象接受任务和时间参数,将任务放到TimerList中,TimerList会按照,Task最初执行时间进行排序
- TimerThread在Timer在被创建时候会成为一个守护线程。
- TimerThread会找到最近调度的执行任务,记录事件后休眠。
- 达到再次执行时间的时候,TimerThread重新执行
- 再一次记录下一哥即将执行的任务后,休眠
缺点:同一时间,只会有一个任务被调度执行。上一个任务的执行会影响下一个任务的启动时间。
多线程调度
执行调度任务的个数为多个
ScheduledExecutor的实现
- 每一被调度的任务,都可以从线程池中,安排一个线程来执行。任务并发执行,不受干扰。
- 会将放入的任务跟线程池匹配实现绑定
方法摘要
案例:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorTest {
public static void main(String[] args) {
//实现调度的线程池,创建一个有10个线程的线程池,而且可以实现调度。
ScheduledExecutorService service =Executors.newScheduledThreadPool(10);
//创建任务
ScheduleTask t1 = new ScheduleTask("小李");
ScheduleTask t2 = new ScheduleTask("小王");
long period =1;
long delay=1;
//线程池绑定,线程会自动将任务给线程
service.scheduleAtFixedRate(t1, delay, period,TimeUnit.SECONDS);
service.scheduleAtFixedRate(t2, delay, period,TimeUnit.SECONDS);
/*
* command - 要执行的任务
Delay - 首次执行的延迟时间
period - 连续执行之间的周期
unit - Delay 和 period 参数的时间单位
* */
}
}
class ScheduleTask implements Runnable{
private String Name ;
public ScheduleTask(String name) {
Name = name;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+Name+"正在工作")
}
}
缺点:
如果要精准定位某个时间点(例如:每个月29号,下午14:28分 12秒)去调度,就很复杂。