我试图找出下面提到的代码背后的原因。这里如果我使用匿名内部类创建Thread,它会进入死锁状态但是使用lambda表达式它可以正常工作。我试图找到这种行为背后的原因,但我不能。
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...");
}
}
使用lambda表达式输出:
Hello guys!!!
Code finished...
匿名课程:
code goes into deadlock state
答案 0 :(得分:5)
使用javap
反编译内部类显示run
方法的以下内容:
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;
请注意,有一个静态合成方法access$0
,后者又调用私有方法call
。创建合成方法是因为call
是私有的,就JVM而言,内部类只是一个不同的类(编译为ThreadCreationTest$1
),无法访问call
。 / p>
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
由于合成方法是静态的,因此它正在等待静态初始化程序完成。但是,静态初始化程序正在等待线程完成,从而导致死锁。
另一方面,lambda版本不依赖于内部类。构造函数的字节码依赖于使用invokedynamic
的{{1}}指令(指令#9):
MethodHandles