我的目标是安排一项以非均匀速率发生的经常性工作。我将从第一个 fragment 迁移到第二个 fragment :
第一:
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG1) {
//recurrent job here
long nextTime = nextTime();
sendMessageAtTime(obtainMessage(MSG1), nextTime);
}
}
}
};
第二:
ScheduledExecutorService mExecutor;
while (true){
mExecutor.schedule(new Callable() {
public Object call() throws Exception {
long startTime = SystemClock.uptimeMillis();
//recurrent job here
delay = nextTime() - startTime ;
return true;
}
}, delay, TimeUnit.MILLISECONDS);
}
我的问题是:
1- 在第一个代码 fragment 中,mHandler 所引用的线程是否可以在作业之间自由执行其他任务或处理其他消息?
2-但是在第二个 fragment 中,线程始终忙于循环。对吗?
3-如何重写第二个代码,以便我不会丢失作业之间的线程 Activity (延迟)?
非常感谢任何帮助
最佳答案
您的第二个代码将无法按预期工作。第一个任务被调度并等待执行后,while
循环继续调度更多任务,所有任务都有相同的延迟。因此,您最终将面临数千甚至数百万个任务。当然,因为主线程正在运行无限循环而没有任何等待,所以它一直很忙。这可能不是您想要的。
您应该更好地使用比上面处理程序使用的类似方法:
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.schedule(() -> {
// do work
// reschedule
executor.schedule(this, nextTime() - System.currentTimeMillis());
}, delay, TimeUnit.MILLISECONDS);
(当然,您还应该检查重新安排时指定的延迟是否不是负数)。
更新:如果您需要单独处理每次执行的结果,则可能需要使用与第二个代码示例类似的另一种方法。它在循环内安排任务执行,并在结果可用时将结果移交给消费者。 (请注意循环内的 future.get()
,它会导致循环线程暂停,直到任务完成)。
public static <T> void schedule(ScheduledExecutorService scheduler,
Schedule schedule, Callable<T> task, Consumer<? super T> consumer)
throws InterruptedException, ExecutionException {
while (true) {
if (Thread.interrupted()) throw new InterruptedException();
long delay = schedule.nextTime() - System.currentTimeMillis();
if (delay < 0) continue; // skip this step
ScheduledFuture<? extends T> future = scheduler.schedule(task,
delay, schedule.getUnit());
consumer.accept(future.get());
}
}
还要注意中断检查,以便其他线程可以通过中断循环线程来停止执行。如果您也想在后台线程上运行该方法,这可以简化在另一个任务中使用此方法的过程。
Schedule
可以是一个提供对调度信息的访问的功能接口(interface):
@FunctionalInterface
public interface Schedule {
long nextTime();
default TimeUnit getUnit() { return TimeUnit.MILLISECONDS; }
}
顺便说一句:android.os.Handler
是在 android 中执行您想要的操作的一种非常好的方法。因此,如果您确实需要它的功能(例如获取 Future
结果),您应该只迁移到 ScheduledExecutorService
。
关于java - 从Handler迁移到ScheduledExecutorService进行调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25212803/