Java 仅在ExecutorService中提交任务时设置变量值
使用Java 仅在ExecutorService中提交任务时设置变量值,java,concurrency,executorservice,java-threads,Java,Concurrency,Executorservice,Java Threads,使用ExecutorService我提交了一批任务,任务有一个时间变量,即GENERAL\u time它们之间的共享。我想在提交任务之前设置GENERAL\u TIME的值。代码如下: ExecutorService executor = Executors.newWorkStealingPool(); ArrayList<Callable<Boolean>> callables = new ArrayList<>(); long GENERA
ExecutorService
我提交了一批任务,任务有一个时间变量,即GENERAL\u time
它们之间的共享。我想在提交任务之前设置GENERAL\u 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);
}
});
}
如何解决这个问题?您的变量是在堆栈上定义的,通常在方法退出后会进行垃圾收集。但是,在lambda中使用该值需要Java在闭包中共享该值,这要求它是final或有效final(不被共享给它的任何代码修改)。因此,任何在线程间保持可变的值都必须包装到一个实例中,该实例本身就是final或实际上是final 实现这一点的最简单也是线程安全的方法是使用
java.util.concurrent.atomic
中的类,在您的例子中是AtomicLong
。变量本身实际上是final或可以声明为final,但可以在任何lambda和线程中设置(和读取)该值:
// declaration
final AtomicLong generalTime = new AtomicLong(0);
// usage acr
generalTime.set(System.currentTimeMillis()));
generalTime.get();
您的变量是在堆栈上定义的,该堆栈通常在方法退出后被垃圾收集。但是,在lambda中使用该值需要Java在闭包中共享该值,这要求它是final或有效final(不被共享给它的任何代码修改)。因此,任何在线程间保持可变的值都必须包装到一个实例中,该实例本身就是final或实际上是final 实现这一点的最简单也是线程安全的方法是使用
java.util.concurrent.atomic
中的类,在您的例子中是AtomicLong
。变量本身实际上是final或可以声明为final,但可以在任何lambda和线程中设置(和读取)该值:
// declaration
final AtomicLong generalTime = new AtomicLong(0);
// usage acr
generalTime.set(System.currentTimeMillis()));
generalTime.get();
导致错误的代码在哪里?此语句
GENERAL\u TIME=System.currentTimeMillis()代码>不在lambda表达式中,不能在后期编辑时导致编译错误。我调用一个使用GENERAL\u TIMESTAMP
作为参数的函数。该行导致so call error.Thx。GENERAL\u TIME
的用法不清楚。您打算对所有线程的执行时间进行计时吗?我很确定lambda的设计不是这样的。常规时间是在创建lambda时捕获的(callables.add()
),规范设计阻止任何其他类型的捕获。导致该错误的代码在哪里?此语句GENERAL\u TIME=System.currentTimeMillis()代码>不在lambda表达式中,不能在后期编辑时导致编译错误。我调用一个使用GENERAL\u TIMESTAMP
作为参数的函数。该行导致so call error.Thx。GENERAL\u TIME
的用法不清楚。您打算对所有线程的执行时间进行计时吗?我很确定lambda的设计不是这样的。一般时间是在创建lambda时捕获的(callables.add()
),规范设计防止任何其他类型的捕获。这似乎是一个很好的解决方案,只需要为OP重新编码一点工作。我经常使用相同的技术在反应式代码和lambda之间共享值。我倾向于使用不可变对象在线程之间共享信息。当从其他语言改编代码和算法时,您的答案似乎是一个很好的通用模式。这似乎是一个很好的解决方案,只需为OP重新编码一点工作。我经常使用相同的技术在反应式代码和lambdas之间共享值。我倾向于使用不可变对象在线程之间共享信息。当从其他语言改编代码和算法时,您的答案似乎是一个很好的通用模式。