Using anonymous runnable class code goes in deadlock state but with lambda it works fine
anonymous-class, java, java-8, lambda, multithreading
Solution
Decompiling with `javap` the inner class shows the following for the `run` method:
public void run();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #12 // Field this$0:Ltest/ThreadCreationTest;
4: invokestatic #22 // Method test/ThreadCreationTest.access$0:(Ltest/ThreadCreationTest;)V
7: return
LineNumberTable:
line 31: 0
line 32: 7
LocalVariableTable:
Start Length Slot Name Signature
0 8 0 this Ltest/ThreadCreationTest$1;
Notice that there is a static synthetic method `access$0` which in turn calls the private method `call`. The synthetic method is created because `call` is private and as far as the JVM is concerned, the inner class is just a different class (compiled as `ThreadCreationTest$1`), which cannot access `call`.
static void access$0(test.ThreadCreationTest);
descriptor: (Ltest/ThreadCreationTest;)V
flags: ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #68 // Method call:()V
4: return
LineNumberTable:
line 51: 0
LocalVariableTable:
Start Length Slot Name Signature
Since the synthetic method is static, it is waiting for the static initializer to finish. However, the static initializer is waiting for the thread to finish, hence causing a deadlock.
On the other hand, the lambda version does not rely on an inner class. The bytecode of the constructor relies on an `invokedynamic` instruction (instruction #9) using `MethodHandles`:
public test.ThreadCreationTest();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=3, args_size=1
0: aload_0
1: invokespecial #13 // Method java/lang/Object."<init>":()V
4: new #14 // class java/lang/Thread
7: dup
8: aload_0
9: invokedynamic #19, 0 // InvokeDynamic #0:run:(Ltest/ThreadCreationTest;)Ljava/lang/Runnable;
14: invokespecial #20 // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
17: astore_1
18: aload_1
19: invokevirtual #23 // Method java/lang/Thread.start:()V
22: aload_1
23: invokevirtual #26 // Method java/lang/Thread.join:()V
26: goto 36
29: astore_2
30: invokestatic #29 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
33: invokevirtual #33 // Method java/lang/Thread.interrupt:()V
36: return
Problem
I am trying to find out the cause behind below mentioned code. Here if I create Thread using anonymous inner class it goes into deadlock state but with lambda expressions it works fine. I tried to find the reason behind this behavior but I could not. ``` public class ThreadCreationTest { static { new ThreadCreationTest(); } private void call() { System.out.println("Hello guys!!!"); } public ThreadCreationTest() { // when we use this thread it goes in deadlock kind of state Thread thread1 = new Thread(new Runnable() { public void run() { call(); } }); // This one works fine. Thread thread = new Thread(() -> call()); thread.start(); try { thread.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public static void main(String... args) { System.out.println("Code finished..."); } } ``` with lambda expression output : ``` Hello guys!!! Code finished... ``` with anonymous class : ``` code goes into deadlock state ```