java自带的ScheduledExecutorService定时任务正常执行一段时间后部分任务不执行

594zzb 发布于 2017/02/03 11:38
阅读 5K+
收藏 0

目前我有用java自带的ScheduledExecutorService线程任务做定时调度功能,我开启了足够多的线程数,比如开了300,实际上用到的只有50个。

我用的是newScheduledThreadPool这种方法做周期性定时任务的,目前发现运行了一段时间都正常,过了几天后,有些定时任务会莫名其妙的不执行,也不报错。比如代码块:

       //开启定时对应数量的任务线程池
        ScheduledExecutorService s = Executors.newScheduledThreadPool(300);
        //高频率定时任务--------------------------------------------------start

        //1分钟执行
        s.scheduleAtFixedRate(new Test1(),0,60000,TimeUnit.MILLISECONDS);

        s.scheduleAtFixedRate(new Test2(),0,60000,TimeUnit.MILLISECONDS);

        s.scheduleAtFixedRate(new Test3(),0,60000,TimeUnit.MILLISECONDS);

然后执行几天正常后,某一天发现只有1仍然定时1分钟执行,但是2和3任务都没执行,也不报错。我知道定时任务里面如果有异常会导致后续不执行,所以我已经在代码里面做了try ... catch的处理了。

public class Test2Service implements Runnable{    
    @Override
    public void run() {
        try{//必须加try-catch防止方法里面异常后下次定时任务不执行
            jobStart();
        }catch (Exception e) {   
            e.printStackTrace();   
            logger.error("定时任务处理异常");
        } 
    }
    
    //定时任务开始
    public void jobStart(){
        //获取当前时分做判断
        Date now = new Date(); 
        SimpleDateFormat dateFormat = new SimpleDateFormat("HHmm");
        String currentMin = dateFormat.format(now);
        dateFormat = new SimpleDateFormat("YYYYMMdd");
        String currentDay = dateFormat.format(now);
        if(QuoteBaseService.useFullTime(currentMin)&&QuoteBaseService.isTradeDay(currentDay)){//有效时间里面才1分钟执行,比如周末都不执行
            hotProfileZstMin();
        }
    }

请问有什么可能会导致这样的情况呢,而且我只要当天在服务器kill掉程序的进程后,重新启动服务就都正常了。。。

当然日志里面有部分定时任务报错了,但是我也都做了异常处理(防止不重新执行)的,目前不知道是怎么回事

加载中
0
whaon
whaon

会不会发生了锁表?

5
594zzb
应该不会,因为在方法的一开始就会有打印开始任务的记录,如果是锁表,那应该会有进入方法的日志才对,而且目前操作的是mongodb
0
温安适
温安适

首先不要为所有任务配置一个线程池,未每一个任务配置一个线程池(每个线程池有自己的任务队列)。线程数量不要过高

ScheduledExecutorService s1 = Executors.newScheduledThreadPool(10);

ScheduledExecutorService s2 = Executors.newScheduledThreadPool(10);

ScheduledExecutorService s3 = Executors.newScheduledThreadPool(10);

我认为你的问题是线程池s内部队列阻塞了,即消费能力太差,1min钟内无法处理完毕3个任务

哈啊哈啊
哈啊哈啊
哈哈
5
594zzb
回复 @混元归一 : 嗯,先调整试试,消费能力之前没有考虑到,确实不少任务都超过了原先预测的时间
温安适
温安适
回复 @594zzb : 建议先调整下,观察下,看看还会不会出问题
温安适
温安适
回复 @594zzb : 不能一概而论,我个人觉得是因为你的消费太慢造成的。如果是消费非常快的任务,你可以一个线程池,线程数量实际上一个应用(或者一个JVM)是有限制的。经验值:非IO密集型 线程数=CPU+1,IO密集型 线程数可以大一些=3*cpu(个人经验)
5
594zzb
意思是假如我这边有50个任务,分别配置50个线程池,然后里面的数量可以设置为1或者稍微多点但又不大的值对吗
0
j
john_guo

线程池中线程的个数是需要根据 CPU的数量和实际的代码执行情况决定的 Runtime.getAvailableProcessers * load factor,感觉上面一个回复挺有道理的  不知道题主 有没有解决呢?

返回顶部
顶部