Java中的Stack Overflow异常

时间:2017-05-17 13:02:21

标签: java

我是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)..

任何人都可以解释它的原因是什么,我该如何解决?

3 个答案:

答案 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解决您的怀疑:
只有当多个线程尝试获取相同的锁时才会发生死锁,并且它不会导致异常 - 通常,死锁的影响是根本没有任何事情发生,锁定的线程永远不会终止。