Java定时任务ScheduledThreadPoolExecutor

以前定时任务一直用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

	}

再看看API的具体信息,总之这是个非常实用的类

public class ScheduledThreadPoolExecutor
    
    
    
    
extends ThreadPoolExecutor
implements ScheduledExecutorService

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.
 }
 

从以下版本开始:
1.5

你可能感兴趣的:(Java定时任务ScheduledThreadPoolExecutor)