安排任务每Y秒运行X次

时间:2018-09-18 15:27:32

标签: java scheduled-tasks scheduledexecutorservice

当前,我正在尝试用Java开发自己的Timer。但是,我发现一个问题是利用ScheduledExecutorService每隔几个TimeUnit运行一个任务并执行一次Runnable X次。目前,我有一个主意,但是如果缩短毫秒数,则会失去精度。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class Timer {

    private static final ScheduledExecutorService SCHEDULER = Executors.newSingleThreadScheduledExecutor();
    private static final ExecutorService SERVICE = Executors.newSingleThreadExecutor();

    private final Runnable action;
    private long initDelay;
    private long delay;

    public Timer(Runnable action, long delay) {
        this.action = action;
        this.delay = delay;
    }

    public Timer(Runnable action, long initDelay, long delay) {
        this.action = action;
        this.initDelay = initDelay;
        this.delay = delay;
    }

    public Future<?>[] runSynchronously(long count) throws InterruptedException {
        List<Future<?>> futures = new ArrayList<>();

        synchronized (SERVICE) {
            SERVICE.wait(initDelay);

            while (count > 0) {
                futures.add(SERVICE.submit(action));
                SERVICE.wait(delay);
                count--;
            }
        }

        return (Future<?>[]) futures.toArray();
    }

    public ScheduledFuture<?> runAsynchronously(long count) {
        ScheduledFuture future = SCHEDULER.scheduleWithFixedDelay(action, initDelay, delay, TimeUnit.MILLISECONDS);
        this.cancel(future, count);
        return future;
    }

    private void cancel(Future future, long count) {
        SCHEDULER.schedule(() -> future.cancel(true), initDelay + (delay * count), TimeUnit.MILLISECONDS);
    }

    private void cancel(ScheduledFuture future, long count) {
        SCHEDULER.schedule(() -> future.cancel(true), initDelay + (delay * count), TimeUnit.MILLISECONDS);
    }
}

目前,当我使用此功能...

final AtomicInteger atom = new AtomicInteger(0);

Timer timer = new Timer(() -> {
    atom.incrementAndGet();
    System.out.println(atom.get());
}, 1000, 1);

timer.runAsynchronously(10);

计数器将达到4。当我之前将延迟更改为333时,它可以产生所有数字。在此之前,我尝试创建一个for循环来重复调度它,但是我不喜欢多个ScheduledFuture<?>实例的积累。

是否可以定义运行多少次,或者创建一个可靠的系统来取消事件而又不损失精度?

0 个答案:

没有答案