2016-11-12 8 views
0

私はシンプルなリソース(Resource.java)を保持するクラスが存在し、 。私は自分のシングルトンクラスの中で2つのスレッドを順番に開始し、静的リソースを消費するようにします。これは、リソースを持つクラスの同期メソッドで行われます。他のチャイルズが利用可能な場合は0
チェック:はい
スレッドのrunメソッドでは、私は上記の同期メソッドを呼び出してから、チョコレートのためのbelow-シングルトンとマルチスレッドで共有リソースを実装する

出力 -

要求として出力を得ます ブロックは
--Student 0仕上げが実行終了---からチョコレートのための
要求:!1
チェックを利用できる他のチャイルズの場合:はい
ブロックが
を終了します- 学生1の実行が終了しました!---

私の質問は、child_1がsynchronizedブロックの実行を終了し、sleep()を実行した後(thread_1は5秒間、thread_2は0秒間スリープします)、もう1つのスレッド)は、child_1が同期ブロックになく、child_1のスリープ時間> child_2の実行時間のために、child_1が起動する前に同期ブロックの実行を開始する必要があります。 child_1は他をブロックしていますか?他のチャイルズが利用可能な場合は0
チェック:1
チェック他のチャイルズが利用可能な場合:はい
ブロックはい
ブロックからチョコレート
要求を終了からチョコレート用
要求出力 - 予想


--Student 1つの仕上げが実行終了!---
--Student 0仕上げを実行!---

これはどのように達成するのですか?

マイコードfile-- シングルトンクラス(ClassRoom.java)

public class ClassRoom { 

private static ClassRoom instance = null; 
private static Student s[]; 

public static ClassRoom getInstance() { 
    if (instance == null) { 
     instance = new ClassRoom(); 
     initStudents(); 
    } 
    return instance; 
} 

private static void initStudents() { 
    s= new Student[2]; 
    s[0] = new Student(0,2,5); 
    s[1] = new Student(1,2,5); 
} 

public Student getStudent(int i) { 
    return s[i]; 
} 
} 

Student.java

public class Student extends Thread { 
int sid; 
int max_choco; 
int allo_choco; 
private Resource resource= new Resource(); 

public Student(int i, int j , int k) { 
    sid = i; 
    allo_choco = j; 
    max_choco = k; 
} 

@Override 
public void run() { 
    try { 
     resource.requestChocolate(sid, 2); 
     Thread.sleep(Math.abs(1-sid)*5000); 
     System.out.println("--Student "+sid+" finishes run!--- "); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 
public int getSid() { return sid;} 

@Override 
public String toString() { 
    return sid+" : "+allo_choco+" : "+max_choco; 
} 
} 

Resource.java

public class Resource { 

private static int total_chocolate = 10; 

public void requestChocolate(int id, int request) { 
    synchronized (Student.class) { 
     System.out.println("Request for chocolate from : "+ 
          ClassRoom.getInstance().getStudent(id).getSid()); 
     if(request <= total_chocolate) { 
      System.out.println("check if other childs available: " 
      +((ClassRoom.getInstance().getStudent((id+1)%2).getSid()>-1 
      && ClassRoom.getInstance().getStudent((id+1)%2).getSid()<3)?"Yes":"No")); { 
      } 
      total_chocolate-=request; 
     System.out.println("block ends"); 
     } else { 
      System.out.println("Request cannot be granted"); 
     } 
    } 
} 
} 

ランナークラス(Test.java )

public class Test { 

public static void main(String args[]) { 
    ClassRoom room = ClassRoom.getInstance(); 
    for(int i = 0 ; i< 2; i++) { 
     room.getStudent(i).run(); 
    } 
} 
} 

答えて

1

あなたはではありません。は、Threadを正しく開始しています。 run()へのあなたの呼び出しはできるだけ同期しています:)。このようにそれを変更し、それが動作します:

ClassRoom room = ClassRoom.getInstance(); 
for(int i = 0 ; i< 2; i++) { 
     room.getStudent(i).start(); 
} 

start()を呼び出すことによって起こるのだろうと、JVMは、新しいスレッドを生成し、そのスレッドにrun()メソッドを呼び出すということです。明らかに、run()を上書きするとコードが実行されることを意味します。違いは、run()を直接呼び出すと、start()内のすべての魔法が失われ、他のメソッドを呼び出して同じスレッドで呼び出しが実行されるということです。

いくつかの他の潜在的なミス:

  • この状況では、StudentではなくThreadを拡張するよりも、Runnableを実施することが望ましいです。理由を理解するためにGoogleの検索を行います。
  • ClassRoomシングルトンはスレッドセーフではありません。後でバグが発生する可能性があります.1つのスレッドでClassRoomを使用することが保証できない場合です。同期をgetInstanceに追加してください。
+0

問題を引き起こしていたstart()の代わりにrun()を呼び出していました。私はそれを修正し、プログラムを動作させました。ありがとう!!!! なぜそれが動作していなかったのかを考えるのに長い時間を費やします.....もう一度おねがいします! –

関連する問題