I am working on a module where a one-time cache is loaded using the static
workflow. Cache loading usually takes around an hour. To improve the performance I am thinking about running these tasks in parallel using a thread pool. Here is the sample code.
Application Startup class:
public class AppStart {
public static void main(String[] args) {
Cache.isValid(); // this will trigger the static workflow
// ...
}
}
Cache loader 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;
}
}
However, in the above case blocking operation future.get
is getting blocked forever, even though it does nothing but a trivial task to return a String.
I also tried using ForkJoinPool
, I had no luck.
I monitored threads using jconsole
could not detect any deadlock. why is it behaving weirdly?
This seems to be the expected behavior. this is a classic class initialization deadlock.
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 gives details on the class initialization process.
I wonder why jconsole
couldn't detect the deadlock