问题描述
在使用timer进行线程调度时出现这样一种问题,求大侠们指教主程序入口public class App { public static void main(String[] args) throws Exception { Timer fileTransportTimer=new Timer("fileTransportTimer"); fileTransportTimer.scheduleAtFixedRate(new FileTransportTimer(), 3000, 1000*30); }}定时任务线程public class FileTransportTimer extends TimerTask{public static boolean isRun = false;public void run() {if (isRun) {return;}isRun = true;SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss");logger.info("开始扫描并发送文件!");try{//扫描目录,判断是否有待发送的文件String path=AppStart.cache.getLocalFilePath();File root=new File(path);if(!root.isDirectory()){throw new Exception("file root is not a directory");}File[] files=root.listFiles();for(int i=0;i<files.length;i++){File tmp=files[i];if(tmp.isFile()){try {MQHandler.sendFile(tmp);} catch (Exception e) {e.printStackTrace();}}break;}logger.info("发送文件任务结束!");}catch(Exception e){logger.error("发送文件任务错误!");e.printStackTrace();}finally{isRun=false;}}}这里已经进行了运行状态的控制,程序确实也是这样的一个执行结果,但每次在执行完成后都会有这样的日志输出2013-02-21 16:01:08 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:01:08 com.rf.util.MQHandler文件War3x.mpq高优先级2013-02-21 16:05:20 com.rf.thread.FileTransportTimer发送文件任务结束!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer发送文件任务结束!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer发送文件任务结束!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer发送文件任务结束!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer发送文件任务结束!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer发送文件任务结束!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer发送文件任务结束!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer发送文件任务结束!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:05:20 com.rf.thread.FileTransportTimer发送文件任务结束!2013-02-21 16:05:38 com.rf.thread.FileTransportTimer开始扫描并发送文件!2013-02-21 16:05:38 com.rf.thread.FileTransportTimer发送文件任务结束!处理文件的时候线程正在运行,新的定时任务不会执行到文件处理的代码部分就会return掉,但当第一个定时任务执行完成后,一下子就打印出了好多后面的这些日志,这点不太明白???
解决方案
引用public void scheduleAtFixedRate(TimerTask task, long delay, long period)安排指定的任务在指定的延迟后开始进行重复的固定速率执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。 在固定速率执行中,根据已安排的初始执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他背景活动)而延迟了某次执行,则将快速连续地出现两次或更多的执行,从而使后续执行能够“追赶上来”。从长远来看,执行的频率将正好是指定周期的倒数(假定 Object.wait(long) 所依靠的系统时钟是准确的)。
解决方案二:
你这里timer调度是单个后台线程,运行过程是这样的:当第一次执行,扫描到文件时,执行发送文件任务,任务执行大概花费时间1000*30*9毫秒,根据scheduleAtFixedRate定义的“在固定速率执行中,根据已安排的初始执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则将快速连续地出现两次或更多的执行,从而使后续执行能够“追赶上来”。从长远来看,执行的频率将正好是指定周期的倒数(假定 Object.wait(long) 所依靠的系统时钟是准确的)”,当任务执行完成后,isRun=false,下一次执行时因为没有文件发送了,任务执行时间很短,所以后面的任务按照之前本应该开始执行的任务,但被第一个长时间任务占用了执行时间,将会快速执行,直到之前遗留任务全部执行完毕后,按照period即1000*30定时执行下次任务。这里你要关注的是,30s一次的任务,1分钟将会安排执行两次,但是如果一次任务超过了30s,后面的任务会安排,但是不会执行,直到上次任务执行,才好进行下一次任务,FixedRate,表示它是按时间周期来安排频率,执行任务的次数正好是时间周期的倒数,不知道这样说,你明白没有?
解决方案三:
定时任务是30s一次,你第一个定时任务执行了4分钟,应该是很多定时任务阻塞住了...我猜的~