以前定时任务一直用Timer这个类,后来发现ScheduledThreadPoolExecutor功能更强大,我们先看个简单的示例,然后再看看API中的描述:
这个定时任务是我的项目中,每隔5分钟去检查设备的在线状态的。
public class CheckDeviceStateExcuter { private static final Log log = LogFactory.getLog(CheckDeviceStateExcuter.class); private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); private static DeviceDao deviceDao = new DeviceDaoImpl(); private static List<DeviceDTO> devices = new ArrayList<DeviceDTO>(); // invoke DLL method to get the details of device static JoymindCommDLLLib instance = JoymindCommDLLLib.INSTANCE; // check states public static void checkStart() { final Runnable checker = new Runnable() { public void run() { System.out.println("check"); devices = deviceDao.queryDevices(); for(DeviceDTO device : devices){ String ip = device.getIp(); String id = "auto_refresh_" + ip; String iniPath = XmlOperationTool.PLAYLIST_TEMPFILE_FOLDER + id + ".ini"; int flag = instance.GetSysInfo(ip, iniPath); if(flag == 1){ // get ini file SystemInfoDTO info = null; try { info = FileOperationTool.parseIni(iniPath); device.setMacAdd(info.getMacAddress()); device.setIp(info.getIp()); device.setGateway(info.getGateway()); device.setOnlineState("在线"); device.setBootTime(info.getBootTime()); device.setDeviceVersion(info.getVersion()); device.setAvailableSpace(info.getFreedisk()); device.setpNo(info.getpNo()); device.setWidth(info.getWidth()); device.setHeight(info.getHeight()); device.setStorage(info.getStorage()); device.setTime(info.getTime()); device.setPrgTotal(info.getPrgTotal()); device.setPrgIndex(info.getPrgIndex()); device.setStatusNo(info.getStatus()); if (info.getStorage().equals("1")) { device.setStorageName("FLASH存储"); } if (info.getStorage().equals("2")) { device.setStorageName("RAM存储"); } if (info.getStorage().equals("3")) { device.setStorageName("SD卡存储"); } device.setCurrentPlaylist(""); device.setCurrentTemplate(""); device.setLastCommunicateTime(""); device.setCurrentTransferFileName(""); device.setCurrentTransferSpeed(""); device.setCurrentPercentage(""); device.setVolume(""); device.setAutoBootTime(""); device.setAutoShutdownTime(""); device.setPlayingVideo(""); device.setProgramUpdateTime(""); device.setProgramUpdateState(""); } catch (IOException e1) { if (log.isErrorEnabled()) { log.error(e1.getMessage()); } e1.printStackTrace(); } boolean addFlag = deviceDao.updateDevice(device); if (addFlag) { if (log.isDebugEnabled()) { log.debug("auto update device "+device.getName()+" successfully"); } } else { if (log.isErrorEnabled()) { log.error("auto update device failed !!!"); } } }else{ deviceDao.updateDevice(ip, "离线"); if (log.isDebugEnabled()) { log.debug("auto update device "+device.getName()+" statue offline"); } } } } }; // 此处的checker是一个线程,1表示启动延迟1个单位开始执行这个线程,然后每隔5分钟执行一次,单位是分钟 final ScheduledFuture<?> checkerHandle = scheduler.scheduleAtFixedRate(checker, 1, 5, TimeUnit.MINUTES); // 这里注释的地方是取消这个定时任务的,是在3600天后停止,因为我这里是检查设备的,所以除非当程序退出才自动停止这个定时任务 /* scheduler.schedule(new Runnable() { public void run() { checkerHandle.cancel(true); } }, 60 * 60, TimeUnit.DAYS); */ } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub }
public class ScheduledThreadPoolExecutor
ThreadPoolExecutor
,它可另行安排在给定的延迟后运行命令,或者定期执行命令。需要多个辅助线程时,或者要求ThreadPoolExecutor
具有额外的灵活性或功能时,此类要优于 Timer
。
一旦启用已延迟的任务就执行它,但是有关何时启用,启用后何时执行则没有任何实时保证。按照提交的先进先出 (FIFO) 顺序来启用那些被安排在同一执行时间的任务。
虽然此类继承自 ThreadPoolExecutor
,但是几个继承的调整方法对此类并无作用。特别是,因为它作为一个使用 corePoolSize 线程和一个无界队列的固定大小的池,所以调整maximumPoolSize 没有什么效果。
扩展注意事项:此类重写 AbstractExecutorService
的 submit 方法,以生成内部对象控制每个任务的延迟和调度。若要保留功能性,子类中任何进一步重写的这些方法都必须调用超类版本,超类版本有效地禁用附加任务的定制。但是,此类提供替代受保护的扩展方法decorateTask(为 Runnable 和 Callable 各提供一种版本),可定制用于通过 execute、submit、schedule、scheduleAtFixedRate 和 scheduleWithFixedDelay 进入的执行命令的具体任务类型。默认情况下,ScheduledThreadPoolExecutor 使用一个扩展FutureTask
的任务类型。但是,可以使用下列形式的子类修改或替换该类型。
public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor { static class CustomTask<V> implements RunnableScheduledFuture<V> { ... } protected <V> RunnableScheduledFuture<V> decorateTask( Runnable r, RunnableScheduledFuture<V> task) { return new CustomTask<V>(r, task); } protected <V> RunnableScheduledFuture<V> decorateTask( Callable<V> c, RunnableScheduledFuture<V> task) { return new CustomTask<V>(c, task); } // ... add constructors, etc. }