在ExecutorService中提交任务时设置变量值[重复]

问题描述 投票:0回答:1

这个问题在这里已有答案:

使用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

我怎么解决这个问题?

java concurrency executorservice java-threads
1个回答
2
投票

您的变量是在堆栈上定义的,通常在方法退出后进行垃圾回收。但是,使用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();
© www.soinside.com 2019 - 2024. All rights reserved.