java 停止scheduleAtFixedRate以计划新任务,直到当前任务完成

oyxsuwqo  于 2023-03-28  发布在  Java
关注(0)|答案(1)|浏览(391)

我有一段代码

public static void main(String[] args){

    ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(5);

    AtomicInteger i = new AtomicInteger(0);
    Runnable runnable = () -> {

        if(i.get() < 5){
            try{ Thread.sleep(2_000); }catch(Exception ignored){ }
        }else if(i.get() >= 15){
            System.exit(0);
        }

        System.out.println(i.getAndIncrement() + " - " + stpe.getQueue().size() + " - " + LocalDateTime.now());

    };

    ScheduledFuture<?> sf = stpe.scheduleAtFixedRate(new Thread(runnable, "Testing"), 0, 1_000, TimeUnit.MILLISECONDS);

}

执行后的控制台:

0 - 0 - 2023-03-27T13:40:04.865501800
 1 - 0 - 2023-03-27T13:40:06.886657500
 2 - 0 - 2023-03-27T13:40:08.890066
 3 - 0 - 2023-03-27T13:40:10.894186200
 4 - 0 - 2023-03-27T13:40:12.898171
 5 - 0 - 2023-03-27T13:40:12.899077100 <---
 6 - 0 - 2023-03-27T13:40:12.899077100 <---
 7 - 0 - 2023-03-27T13:40:12.900068700 <---
 8 - 0 - 2023-03-27T13:40:12.900068700 <---
 9 - 0 - 2023-03-27T13:40:12.900068700 <---
10 - 0 - 2023-03-27T13:40:12.901073800 <---
11 - 0 - 2023-03-27T13:40:13.857069500
12 - 0 - 2023-03-27T13:40:14.852331500
13 - 0 - 2023-03-27T13:40:15.860971200
14 - 0 - 2023-03-27T13:40:16.865873300

正如你所看到的,我有一个Thred.sleep(2_000)用于前5次执行,之后我让它们以ScheduledFuture的速度执行,直到第15次执行,这将停止程序。
我知道scheduleAtFixedRate在当前执行完成之前不会开始新的执行。
但相反,是在等待队列中添加它们,从那里是采取一个接一个,并执行不尊重率.
正如你所看到的,从5到10,和4一样在同一秒。执行5-10在等待队列中,一个接一个地执行,没有速率。它们之间的差异,作为时间,只是执行时间。
在等待队列被释放后,它以这个速度从11点持续到14点。
我如何才能避免5-10个执行是一个接一个立即,而是以固定的速度(~1_000毫秒)执行?我可以找到这个等待队列,并释放它?
我希望task 0结束和task 1开始之间的时间是1 s- task0_execution_time(就像scheduledAtFixedRate一样),但不要有可以累积任务的等待队列。
例如:
1.启动task 1,执行时间为5s。
1.启动task 2而不暂停(1 s- 5s = -4s =〉即时启动)。
1.在1 s- task2_execution_time时启动task 3。
不要将task 2和task 3累积在等待队列中并在稍后立即执行它们,因为task 1的执行时间为5s,而task 2和task 3计划在这5s期间启动

wgmfuz8q

wgmfuz8q1#

我根本不会使用执行器。一个简单的for循环和一个变量sleep完全可以满足你的要求:

import java.time.LocalTime;

public class Main {

    public static void main(String[] args) throws InterruptedException {
        long previousStartTime;
        for (int i = 0; i < 15; ++i) {
            previousStartTime = System.currentTimeMillis();
            System.out.println(LocalTime.now().toString() + " doing task " + i);
            Thread.sleep(i < 5 ? 2000: 0);
            long taskTime = System.currentTimeMillis() - previousStartTime;
            System.out.println("   Task took " + taskTime);
            long timeToWait = Math.max(0L, 1000L - taskTime);
            System.out.println("   Waiting " + timeToWait);
            Thread.sleep(timeToWait);
        }
    }
}

相关问题