我写了这段代码:
ScheduledExecutorService ExtractorTimer=Executors.newScheduledThreadPool(1);
final ScheduledFuture<?> SchedulerHandle;
SchedulerHandle =ExtractorTimer.scheduleWithFixedDelay(
new Runnable() {
public void run() {
if(DB.buildConnection()){
SchedulerHandle.cancel(false);
}
}
},0, 60,java.util.concurrent.TimeUnit.SECONDS);
它给出了这个:
Variable SchedulerHandle might not have benn initialized
有什么问题?
我该如何解决?
答案 0 :(得分:1)
编译器是正确的。这里确实存在问题。
问题出现是因为Java处理匿名SchedulerHandle
类中Runnable
变量的使用方式。实例化Runnable
类时,使用合成构造函数参数将SchedulerHandle
的值传递给匿名类。这个值存储在一个隐藏属性中,这就是run()
方法使用的...而不是包含该类的范围中的变量。
那为什么会导致错误?
嗯,我上面描述的机制意味着在SchedulerHandle
实例创建之前需要初始化Runnable
。但实际上,在scheduleWithFixedDelay
调用返回后,它会在稍后初始化。因此,当需要变量的值时,它尚未初始化。
答案 1 :(得分:0)
因为SchedulerHandle是最终的并且您没有立即定义它,所以编译器会警告您,它可能没有在run()方法中初始化。
只需:
final ScheduledFuture SchedulerHandle = ExtractorTimer.scheduleWithFixedDelay(...
更新:这完全错了。让我们看看,你想每60秒调用一次DB.buildConnection(),直到它返回true。遗憾的是,您无法引用从调用方法的Runnable中的scheduleWithFixedDelay()返回的SchedulerHandle,因为必须首先定义Runnable - 但它不知道SchedulerHandle是什么,因为它在那时不存在。
因此取消流程的另一种方法是终止ScheduledExecutorService,如下所示:
ScheduledExecutorService ExtractorTimer=Executors.newScheduledThreadPool(1);
final ScheduledFuture<?> SchedulerHandle;
SchedulerHandle =ExtractorTimer.scheduleWithFixedDelay(
new Runnable() {
public void run() {
if(DB.buildConnection()){
ExtractorTimer.shutdown();
}
}
},0, 60,java.util.concurrent.TimeUnit.SECONDS);
但请注意,如果您这样做,则无法重复使用ExtractorTimer,并且任何给定任务将被取消!未来的schedule()s也将不会执行。使其可用的唯一方法是创建一个新的ScheduledExecutorService - 这是这种方法的缺点。
因此,如果你只使用ExtractorTimer来完成这一项任务,一切都应该没问题。
答案 2 :(得分:-2)
尝试:
final ScheduledFuture<?> SchedulerHandle = null;