无法在静态工作流/块中使用ExecutorService执行任务

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

我正在使用static工作流程加载一次性缓存的模块上工作。缓存加载通常需要一个小时左右。为了提高性能,我正在考虑使用线程池并行运行这些任务。这是示例代码。应用程序启动类:

public class AppStart {
    public static void main(String[] args) {
        Cache.isValid();  // this will trigger the static workflow
        // ...
    }
}

缓存加载器类:

public class Cache {

    static {
        System.out.println("Static block initialization started!");
        initialize();
        System.out.println("Static block initialization finished!");
    }

    public static void initialize( ) {
        System.out.println("initialize() started!");
        ExecutorService executorService = Executors.newSingleThreadExecutor(); // will replace with fixedThreadPool
        Future<String> future = executorService.submit(() -> "Hello world!");
        System.out.println("Retrieve the result of the future");
        String result = null;
        try {
            result = future.get();
            System.out.println(result);
        } catch( InterruptedException e ) {
            e.printStackTrace();
        } catch( ExecutionException e ) {
            e.printStackTrace();
        }
        executorService.shutdown();
    }

    public static boolean isValid( ) {
        return true;
    }
}

但是,在上述情况下,阻塞操作future.get会永远被阻塞,即使它只是执行返回字符串的琐碎任务而已。

我也尝试过使用ForkJoinPool,但我没有运气。

我使用jconsole监视线程无法检测到任何死锁。为什么它表现怪异?

java future executorservice forkjoinpool
2个回答
0
投票

您的Cache类的静态初始值设定项未完成-它正在等待future.get()的完成。您可以删除static初始化程序,然后直接从Cache.initialize()或其他地方调用您的方法– main(),但是无论如何执行该操作都会被类似地阻塞。

我建议您创建一个单独的线程来调用initialize(),从而避免阻塞行为,如下所示:

new Runnable() {
    @Override
    public void run() {
        initialize();
    }
}.run();

0
投票

这似乎是预期的行为。这是经典的类初始化死锁。

使用依赖于类的静态初始化完成的Runnable启动新线程。继而,由于future.get()方法调用,该类正在等待Runnable完成。静态初始化正在等待线程完成,而线程正在等待静态初始化完成。

[JLS:: Class initialiization提供有关类初始化过程的详细信息。

我想知道为什么jconsole无法检测到死锁

© www.soinside.com 2019 - 2024. All rights reserved.