2017-05-17 12 views
2

スレッドに慣れていません。私は今、私は、Runnableインタフェースを実装して他の二つのクラスを作成したフォローJavaでのスタックオーバーフロー例外

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"); 
    } 
} 

ように2つのクラス名のAとBを作成しました。 mainメソッドで

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(); 
    } 

} 

私はこのコードを実行しているとき、私は以下のコード -

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

どのような原因が原因であるのか、どのように解決できますか?

+4

オブジェクトの 'foo()'メソッドを呼び出すと、無限の再帰呼び出しシーケンスが得られます。 –

答えて

11

あなたは何を期待しましたか?

あなたは、スタックオーバーフローするまで、その上Afoo()メソッドを呼び出し、そしてBfoo()メソッドを呼び出すAfoo()方法を持っています。

これは、循環メソッド呼び出しを避けることで解決できます。

+0

ある人が私にこの問題を与え、スレッドセーフな方法を教えてくれましたか? –

+0

これはややこしい質問ですか?私はスレッドに新しいです。私はそれがDeadLockの状況だと思った。 –

+1

@SubhabrataMondalデッドロックではありません。 Eranが言及したように、それは循環呼び出しです。別の質問がある場合は、新しい投稿でそれを尋ねる必要があります。 – bradimus

1

関数を呼び出すと、呼び出された関数のアドレスがスタックに保存され、関数が完了するとスタックが削除されます。 A.fooではB.fooを呼び出し、B.fooではA.fooを呼び出します。だからあなたのスタックはB.fooとA.fooのアドレスで埋められます。ループは終了することはありませんが、スタックのサイズは決まります。だから私は無限ループを解消しようとすることをお勧めします。私は専門家ではないので、どのようにあなたに伝えることはできません。

0

すでに述べたように、StackOverflowErrorはスレッドとは関係ありません。おそらく単純化された例では、これをより明確にすることができます。それはどんなThread Sが含まれていない次のコードを使用して再現することができ

:...最終的には、スタックオーバーフローにつながるA.foo呼び出す

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。あなたの例では、が1つしかありません。ここにはメインスレッドがあります。t1です。 Runnable r2はまったく実行されていません。

the comments on another questionからあなたの疑惑に対処するには:複数のスレッドが同じロックを取得しようとした場合、デッドロックにのみ発生する可能性があり、それは例外にはつながらないだろう
- 一般的に、デッドロックの効果は何もまったく起こらないということですロックされたスレッドは決して終了しません。

関連する問題