一、推荐使用的调度器和线程池
1、调度器
//2个线程的调度器
private static ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(2);
//5秒钟后每3分钟执行一次
pool.scheduleAtFixedRate(new TestTask(), 5, 60 * 3, TimeUnit.SECONDS);
;
2、线程池
//10个线程的线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
//执行一个线程
pool.execute(new TestTask());
线程:
class TestTesk implements Runnable{
@Override
public void run() {
System.out.println("执行2....");
}
}
二、timer和timertask
Timer是一种线程设施,用于安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可以调度TimerTask。TimerTask是一个抽象类,实现了Runnable接口,所以具备了多线程的能力。
一个Timer可以调度任意多个TimerTask,它会将TimerTask存储在一个队列中,顺序调度,如果想两个TimerTask并发执行,则需要创建两个Timer。下面来看一个简单的例子:
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
static class MyTimerTask1 extends TimerTask {
public void run() {
System.out.println("爆炸!!!");
}
}
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new MyTimerTask1(), 2000);// 两秒后启动任务
//已当前时间为起点,每隔两秒执行一次
//timer.schedule(new MyTimerTask1(), new Date(), 2000);// 两秒后启动任务 }
}
三、比较
Timer对调度的支持是基于绝对时间的,因此任务对系统时间的改变是敏感的;而ScheduledThreadPoolExecutor支持相对时间。
Timer使用单线程方式来执行所有的TimerTask,如果某个TimerTask很耗时则会影响到其他TimerTask的执行;而ScheduledThreadPoolExecutor则可以构造一个固定大小的线程池来执行任务。
Timer 不会捕获由TimerTask抛出的未检查异常,故当有异常抛出时,Timer会终止,导致未执行完的TimerTask不再执行,新的 TimerTask也不能被调度;ScheduledThreadPoolExecutor对这个问题进行了妥善的处理,不会影响其他任务的执行。
总结:timer任务一旦有一个出错那么所有的任务都会中断,而ScheduledThreadPoolExecutor只会停止出错任务而不会停止其他任务
下面是一个ScheduledThreadPoolExecutor出错的例子:
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ScheduleTest {
public static void main(String[] args) {
ScheduledThreadPoolExecutor schedule = new ScheduledThreadPoolExecutor(2);
schedule.scheduleAtFixedRate(new TestTesk(), 2, 5, TimeUnit.SECONDS);
schedule.scheduleAtFixedRate(new TestTesk2(), 2, 5, TimeUnit.SECONDS);
}
}
class TestTesk implements Runnable{
@Override
public void run() {
System.out.println("执行1....");
String a = null;
System.out.println(a.length());
}
}
class TestTesk2 implements Runnable{
@Override
public void run() {
System.out.println("执行2....");
}
}