无法在静态 workflow/block 中使用 ExecutorService 执行任务

Unable to execute task using ExecutorService in static workflow/block

我正在开发一个模块,其中使用 static 工作流程加载一次性缓存。缓存加载通常需要大约一个小时。为了提高性能,我正在考虑 运行 使用线程池并行执行这些任务。这是示例代码。

应用程序启动class:

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

缓存加载器class:

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 将永远被阻塞,尽管它只是对 return 字符串执行一项微不足道的任务。

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

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

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

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

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

这似乎是预期的行为。这是一个 classic class 初始化死锁。

a new Thread is started using the Runnable that is dependent on the completion of static initialization of a class. The class is, in turn, waiting for the Runnable to finish because of the future.get() method call. The static initialization is waiting for thread to complete and thread is waiting for static initialization to complete.

JLS:: Class initialiization 详细介绍了 class 初始化过程。

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