在 ExecutorService 提交任务时设置变量值
set variable value just at submitting task in ExecutorService
使用 ExecutorService
我提交了一批任务,任务有一个时间变量,即 GENERAL_TIME
在它们之间共享。我想在提交任务之前设置 GENERAL_TIME
的值。这是代码:
ExecutorService executor = Executors.newWorkStealingPool();
ArrayList<Callable<Boolean>> callables = new ArrayList<>();
long GENERAL_TIME = 0;
for (String i : host.getHosts()){
callables.add(
() -> {
ESBRun.monitorOSMetrics(
db, COMPONNENT_TYPE, GENERAL_TIME, metric, ssh, i
);
return true;
}
}
GENERAL_TIME = System.currentTimeMillis();
executor.invokeAll(callables)
.stream()
.map(future -> {
try {
return future.get();
}
catch (Exception e) {
throw new IllegalStateException(e);
}
});
}
但它出错
variable used in lambda should be final or effectively final java
我该如何解决?
您的变量是在堆栈上定义的,通常会在方法退出后被垃圾回收。但是,在 lambda 中使用该值需要 Java 在闭包中共享该值,这要求它是最终的或实际上是最终的(不被共享到的任何代码修改)。因此,任何要在线程间保持可变的值都必须包装到一个实例中,该实例本身是最终的或实际上是最终的。
实现此目的的最简单且线程安全的方法是使用 java.util.concurrent.atomic
中的 类,在您的情况下为 AtomicLong
。变量本身将是有效的 final 或可以声明为 final,但可以在任何 lambda 和线程中设置(和读取)该值:
// declaration
final AtomicLong generalTime = new AtomicLong(0);
// usage acr
generalTime.set(System.currentTimeMillis()));
generalTime.get();
使用 ExecutorService
我提交了一批任务,任务有一个时间变量,即 GENERAL_TIME
在它们之间共享。我想在提交任务之前设置 GENERAL_TIME
的值。这是代码:
ExecutorService executor = Executors.newWorkStealingPool();
ArrayList<Callable<Boolean>> callables = new ArrayList<>();
long GENERAL_TIME = 0;
for (String i : host.getHosts()){
callables.add(
() -> {
ESBRun.monitorOSMetrics(
db, COMPONNENT_TYPE, GENERAL_TIME, metric, ssh, i
);
return true;
}
}
GENERAL_TIME = System.currentTimeMillis();
executor.invokeAll(callables)
.stream()
.map(future -> {
try {
return future.get();
}
catch (Exception e) {
throw new IllegalStateException(e);
}
});
}
但它出错
variable used in lambda should be final or effectively final java
我该如何解决?
您的变量是在堆栈上定义的,通常会在方法退出后被垃圾回收。但是,在 lambda 中使用该值需要 Java 在闭包中共享该值,这要求它是最终的或实际上是最终的(不被共享到的任何代码修改)。因此,任何要在线程间保持可变的值都必须包装到一个实例中,该实例本身是最终的或实际上是最终的。
实现此目的的最简单且线程安全的方法是使用 java.util.concurrent.atomic
中的 类,在您的情况下为 AtomicLong
。变量本身将是有效的 final 或可以声明为 final,但可以在任何 lambda 和线程中设置(和读取)该值:
// declaration
final AtomicLong generalTime = new AtomicLong(0);
// usage acr
generalTime.set(System.currentTimeMillis()));
generalTime.get();