我是Thread的新手。我创建了两个名为A和B的类,如下所示 -
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
synchronized void foo() {
b.foo();
System.out.println("Hi A");
}
}
public class B {
private A a;
public void setA(A a) {
this.a = a;
}
synchronized void foo() {
a.foo();
System.out.println("Hi B");
}
}
现在我创建了另外两个实现Runnable接口的类。
public class AThread implements Runnable{
private A a;
public AThread(A a){
this.a = a;
}
@Override
public void run() {
a.foo();
}
}
public class BThread implements Runnable {
private B b;
public BThread(B a){
this.b = b;
}
@Override
public void run() {
b.foo();
}
}
在main方法中,我编写了以下代码 -
public static void main(String args[]) {
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
Runnable r1 = new AThread(a);
Runnable r2 = new BThread(b);
Thread t1 = new Thread(r1);
t1.start();
}
当我运行此代码时,我得到以下异常。
Exception in thread "Thread-0" java.lang.StackOverflowError
at student.B.foo(B.java:21)
at student.A.foo(A.java:21)..
任何人都可以解释它的原因是什么,我该如何解决?
答案 0 :(得分:11)
你期待什么?
foo()
中A
方法调用foo()
B
方法中的foo()
方法调用了A
中的@model IEnumerable<string>
<label asp-for="@ViewData["AspFor"]"></label>
<input asp-for="@ViewData["AspFor"]" value="@Model.FirstOrDefault()">
方法,因此打开,直到堆栈溢出。
您可以通过避免循环方法调用来解决它。
答案 1 :(得分:1)
如果你调用一个函数,那么堆栈会保存它所调用的函数的地址,并且只有在函数完成后才会删除它。在A.foo中你打电话给B.foo,在B.foo你打电话给A.foo。所以你的堆栈充满了B.foo和A.foo的地址。循环永远不会结束,但堆栈的大小确实如此。所以我建议尝试消除无限循环。无法告诉你,因为我不是专家。
答案 2 :(得分:0)
正如其他人已经提到的,StackOverflowError
与线程无关。也许一个简单的例子可以使这更清楚。
可以使用以下代码复制它,该代码不包含任何Thread
s:
public static void main(String args[]) {
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
a.foo();
}
A.foo
调用B.foo
调用A.foo
,最终会导致堆栈溢出。在您的示例Thread
中,只有一个t1
涉及,这里是主线程。你永远不会执行Runnable r2
。
从the comments on another question解决您的怀疑:
只有当多个线程尝试获取相同的锁时才会发生死锁,并且它不会导致异常 - 通常,死锁的影响是根本没有任何事情发生,锁定的线程永远不会终止。