当前,我正在尝试用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<?>
实例的积累。
是否可以定义运行多少次,或者创建一个可靠的系统来取消事件而又不损失精度?