推荐还是用第二种方法,即用ScheduledThreadPoolExecutor,因为它不需要像timer那样需要在里面再用一个线程池来保证计时的准确。(前提是线程池必须要大于1个线程)
1.timer中用线程池来执行任务,可以保证开始执行时间的准确,具体结束时间要以任务需要执行时间为准。如果未使用线程池,执行时间将被任务执行时间所影响。
package timer; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import ch.qos.logback.core.joran.action.NewRuleAction; public class test {
private static final Logger log = LoggerFactory.getLogger(test.class); SimpleDateFormat sdformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws InterruptedException {
log.info("main start");
Timer timer = new Timer();
MyTask myTask = new MyTask("ONE");
MyTask myTask2 = new MyTask("TWO");
// 多长时间(毫秒)后执行任务
// timer.schedule(new MyTask(), 1000);
// 设定某个时间执行任务
// timer.schedule(new MyTask(), new Date(System.currentTimeMillis() +
// 1000 * 2));
// 第一次在指定firstTime时间点执行任务,之后每隔period时间调用任务一次。
// timer.schedule(new MyTask(), new Date(System.currentTimeMillis() +
// 1000 * 60*3),1000);
// delay时间后开始执行任务,并每隔period时间调用任务一次。
timer.scheduleAtFixedRate(myTask, 1000 * 3, 3000);
// timer.scheduleAtFixedRate(myTask2, 1000 * 3, 3000);
// 第一次在指定firstTime时间点执行任务,之后每隔period时间调用任务一次。
// timer.scheduleAtFixedRate(myTask, new Date(System.currentTimeMillis()
// + 1000 * 1), 2000); TimeUnit.SECONDS.sleep(10);
// timer.cancel();
// myTask.cancel();
// myTask2.cancel();
log.info("timer cancel");
}
} class MyTask extends TimerTask {
ExecutorService mExecutorService= Executors.newFixedThreadPool(3);
private static final Logger log = LoggerFactory.getLogger(test.class);
SimpleDateFormat sdformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private String s; public MyTask(String s) {
this.s = s;
} @Override
public void run() { mExecutorService.execute(new Runnable() {
public void run() {
log.info(s + " 1 " + sdformat.format(new Date(System.currentTimeMillis())));
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info(s + " 2 " + sdformat.format(new Date(System.currentTimeMillis())));
}
}); }
}
2.ScheduledThreadPoolExecutor类分scheduleWithFixedDelay和scheduleAtFixedRate方法,前者不包含执行时间,后者包含执行时间。
两种方法中如果都不再使用线程池,执行的开始时间也都会受执行时间影响。
package timer; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimerTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class ScheduledThreadPoolExecutorTest {
private static final Logger log = LoggerFactory.getLogger(test.class);
SimpleDateFormat sdformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws InterruptedException {
MyTask2 task = new MyTask2("ONE");
MyTask2 task2 = new MyTask2("TWO");
ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(5);
// stpe.scheduleWithFixedDelay(task, -2, 3, TimeUnit.SECONDS);
// stpe.scheduleWithFixedDelay(task2, -2, 3, TimeUnit.SECONDS);
ScheduledFuture<?> sf=stpe.scheduleAtFixedRate(task, -2, 3, TimeUnit.SECONDS);
TimeUnit.SECONDS.sleep(3);
// sf.cancel(false);
// stpe.shutdown();
}
} class MyTask2 extends TimerTask {
private static final Logger log = LoggerFactory.getLogger(test.class);
SimpleDateFormat sdformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private String s; public MyTask2(String s) {
this.s = s;
} @Override
public void run() {
log.info(s + " 1 " + sdformat.format(new Date(System.currentTimeMillis())));
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info(s + " 2 " + sdformat.format(new Date(System.currentTimeMillis())));
}
}