如果前一个任务未完成,如何启动ScheduledExecutorService任务

时间:2018-01-19 06:00:47

标签: java multithreading scheduledexecutorservice

我的问题是我们必须给它一个修复的时间表来启动任务。让我说我给10秒钟,我的任务平均完成时间为10-15秒。因此,在quque中等待线程一段时间后会导致巨大的内存消耗。如果我使用syncronized进行上述方法,则会出现问题。如果我不使用syncronized那么我浪费资源(cpu)因为如果没有完成我不需要运行任务。所以我认为递归调用任务的解决方案,但我相信递归线程会增加更多的内存问题......我该怎么办?不久我只想在完成任务时调用它。不固定的时间。

public void myScheduledTask{
    doJob(); ( use countdown latch to control waiting if necessary)
    TimeUnit.SECONDS.sleep(x);
    new Thread( new Runnable( { mySchedulTask();   } ));
    or
    executor.execute( a thread that call myScheduledTask() method);
}

2 个答案:

答案 0 :(得分:2)

听起来像你想要完成的选项:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(count);
ScheduledFuture<?> future = executor.scheduleWithFixedDelay(
                                   task, 
                                   delay, 
                                   delay, 
                                   TimeUnit.MILLISECONDS
                                  );

这将启动您的任务并在上一次完成后delay毫秒后执行它。 Count应该是您要使用的线程数,1是可以接受的。这也允许您使用将来停止任务。

你的例子的问题。 a)你正在执行者线程上睡觉。不要这样做让执行者处理它。如果你使用1的线程池,那么这个执行器在你等待的时候就无法做任何工作。 b)启动一个新线程正在从执行程序中获取控制权...只需使用执行程序,然后就可以控制执行。

如果你真的想坚持使用你的表格。

class RecurringTask implements Runnable{
    @Override
    public void run(){
        doJob();
        executor.schedule(this, delay, TimeUnit.MILLISECONDS); 
    }
}

现在你将创​​建一个你从未使用的Futures,因此控制任务的执行将更加困难。

答案 1 :(得分:0)

在任务类中创建静态成员 - 锁定。 在doJob中,如果已经获得锁定,则避免执行作业:

 if (lock.tryLock()) {
      try {
          // do the job
      } finally {
          lock.unlock();
      }
  } else {
      // log the fact you skipped the job
      return;
  }