2011-01-13 4 views
5

私はクラスNoteとクラスMeetingを持っています。 にnoteListという名前のArrayListがあります。 Meetingのオブジェクトが作成されると、noteListに登録されます。同時に2つのスレッドを開始する方法(または終了時に)

メインクラスで、Meetingという2つのオブジェクトを同時に(またはクローズ時に)作成できるようにしたいだけです。私のプログラムは次のとおりです。

public class Note{ 
    //some field and method hier 
    public void add(Meeting m){ 
     notes.add(m); 
    } 
    private static final List<Entry> notes = 
     Collections.synchronizedList(new ArrayList<Entry>()); 
} 

public class Meeting implements Runnable{ 
    public Meeting(Note note_1,Note note_2,Calendar calendar){ 
     note_1.add(this); 
     note_2.add(this);} 
     //some method 
    } 

    public class Test implements Runnable{ 
     public static void main(String[] args) { 
      Note note_1 = new Note();     
      Note note_2 = new Note(); 
      Meeting m_1 = new Meeting(note_1,note_2); 
      Meeting m_2 = new Meeting(note_2,note_1) 
      Thread t1 = new Thread(m_1); 
      Thread t2 = new Thread(m_2) 
      t1.start(); 
      t2.start(); 
     } 
     //t1,t2 are two thread and they start one to one(not at the same time). 

私はwait()notify()またはnotifyAll()を使用することができることをどこか読みましたが、彼らは同期の方法で使用する必要があります。自分のプログラムには同期メソッドがありません。

+0

あなたのコードでは、GCは、それらをクリーンアップすることを決定するまで、彼らは両方のメモリに同時に存在することになるもののm_2' ''前に、書かれたm_1'は常に作成(インスタンス化)されます。他に何か意味がありますか?いずれにしても、シングルトンのダブルチェックロックが機能しない理由を検索した場合、Javaの同期に関する問題の概要が非常によくわかります。 – CurtainDog

+0

私は欠けていると思います。私はどのようにm_1とm_2を同時に(インスタンス化して)同時に作ることができるのかを示します。 – echo

+0

synchronizedList()はすべてのメソッドを同期させたリストを返すので、synchronizedメソッドを使用しています。 –

答えて

15

これは、2つのスレッドを開始するのと同じくらいです。

実行方法をさらに同期させるには、実行方法の最上部にあるCountDownLatchで待機させることができます。

これは、スレッドの作成と起動(実行メソッドが実行される前に発生する部分)と、いくつかのフリークスケジューリングの奇妙さを取り除くオーバーヘッドを取り除くものです。ただし、実際にラッチが実行された後のコードがどのように同時に実行されるかは保証されません。

CountDownLatch latch = new CountDownLatch(2); 

Runnable r1 = new Meeting(latch); 
Runnable r2 = new Meeting(latch); 


// in Meeting 

private final CountDownLatch latch; 

public void run(){ 

    latch.countDown(); 
    latch.await(); 

    // other code 
} 
+1

+1また、http://stackoverflow.com/questions/1909622を参照してください。 – trashgod

+0

2つ目のスレッドがcountDownに達するまで、1つのスレッドが待機していないことを保証できます。これにより、両方が開始されたが、直後に実行を停止することができます。 –

+0

@Peter Lawrey:そうです、つまり、「ラッチが実際にどのように実行されるかは保証されません」という意味です。あなたが望むのであれば、あなたが強制することができるのは厳密な注文です。 – Thilo

8

残念ながら、同時にでを二つのスレッドを起動する方法はありません。

まず、シーケンスt1.Start();t2.Start();がt1で実行され、その後、t2で実行されます。これは、、スレッドt1がスレッド2の前にスケジューリングされていることを意味します。 2つの方法はそれぞれ1秒の割合を取るので、それらが連続しているという事実は人間の観察者には見えません。

さらに、Javaスレッドはという予定で、です。 に割り当てられ、最終的にが実行されます。マルチコアCPUを持っていても、1)スレッドが並列に実行されていて(他のシステムプロセスが干渉する可能性がある)、2)スレッドが両方ともStart()メソッドが呼び出された直後に開始されていることがわかりません。

+1

同時に2つのスレッドを開始することはできませんが、runメソッドで同期できます。もちろん、最終的な実行についてあなたが言ったのは、まだ適用されます。しかし、少なくともいくつかの相互依存関係がある場合は、runメソッドが実行される順序を調整することができます。 – Thilo

+0

スレッドや複数のCPUを扱っているときは、「同時に」ということはありません。あなたはあなたの質問を明確にする必要があります。 – EJP

1

"close"から同じ時刻に開始しています。ポイントは、コードがt1.start()でブロックされていないことです。

Meetingクラスのrun()メソッドの上部にprintステートメントを追加し、t2.start()の直後にもう1つのprintステートメントを追加すると、これを確認できます。このような何か:

public class Meeting implements Runnable { 
    private String name; 
    public Meeting(String name) { 
     this.name = name; 
    } 
    public void run() { 
     System.out.println(name + " is running"); 
    } 
} 

public class Test { 
    public static void main(String[] args) { 
     Meeting m_1 = new Meeting("meeting 1"); 
     Meeting m_2 = new Meeting("meeting 2") 
     Thread t1 = new Thread(m_1); 
     Thread t2 = new Thread(m_2) 
     t1.start(); 
     t2.start(); 
     System.out.println("this might print first!"); 
    } 
} 

// possible output: 
> this might print first! 
> meeting 1 is running 
> meeting 2 is running 
関連する問題