2011-01-13 35 views
5

Tôi có một lớp Note và một lớp học Meeting. Có một số ArrayList có tên noteList trong lớp Note. Khi một đối tượng của Meeting được tạo, sau đó nó được đăng ký trong noteList.cách bắt đầu hai chủ đề cùng một lúc (hoặc tại thời điểm đóng)

Tôi chỉ muốn phân giải trong lớp chính có thể tạo hai đối tượng Meeting cùng một lúc (hoặc vào thời gian gần). chương trình của tôi là:

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

Tôi đã đọc ở bất cứ đâu mà wait(), notify() hoặc notifyAll() có thể được sử dụng, nhưng chúng phải được sử dụng trong một phương pháp đồng bộ. Tôi không có phương pháp đồng bộ trong chương trình của mình.

+0

Trong mã của bạn như được viết, 'm_1' luôn được tạo (instantiated) trước' m_2' mặc dù cả hai sẽ tồn tại đồng thời trong bộ nhớ cho đến khi GC quyết định xóa chúng. Bạn có ý gì khác không? Trong bất kỳ trường hợp nào nếu bạn tìm kiếm lý do tại sao đôi kiểm tra khóa cho singletons không làm việc bạn sẽ nhận được một tổng quan rất tốt về các vấn đề đồng bộ hóa trong Java. – CurtainDog

+0

Tôi nghĩ rằng có một thiếu.Tôi có nghĩa là làm thế nào có thể m_1 và m_2 được tạo ra (instantiated) cùng một lúc (hoặc tại thời điểm gần) – echo

+0

Bạn đang sử dụng phương pháp đồng bộ vì synchronListList() trả về một danh sách có tất cả các phương pháp của nó đồng bộ. –

Trả lời

15

Điều này gần như bạn sắp bắt đầu hai chuỗi.

Những gì bạn có thể làm để đồng bộ hóa các phương thức chạy thậm chí nhiều hơn là yêu cầu họ đợi trên CountDownLatch ở đầu phương pháp chạy của chúng.

Điều này có nghĩa là lấy đi chi phí tạo và bắt đầu luồng (phần xảy ra trước khi phương thức chạy của bạn được thực hiện), và cũng có thể có một số kỳ quặc lập lịch kỳ quái. Tuy nhiên, bạn không có sự bảo đảm, cách mã đồng thời sau khi chốt thực sự sẽ được thực hiện.

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 Xem thêm, http://stackoverflow.com/questions/1909622 – trashgod

+0

Bạn chỉ có thể đảm bảo rằng một chuỗi không vượt qua đang đợi cho đến khi chuỗi thứ hai đạt đến countDown. Điều này đảm bảo cả hai đều bắt đầu nhưng có thể ngừng chạy ngay sau đó. –

+0

@Peter Lawrey: Vâng, đó là những gì tôi có nghĩa là "bạn không có bảo đảm tuy nhiên, làm thế nào đồng thời mã sau khi chốt thực sự sẽ được thực hiện". Tất cả những gì bạn có thể thực thi là một thứ tự nghiêm ngặt, nếu bạn muốn điều đó. – Thilo

8

Thật không may, không có cách nào để bắt đầu hai luồng cùng lúc.

Để tôi giải thích tốt hơn: trước hết, chuỗi t1.Start();t2.Start(); được thực thi với t1 trước và sau đó, t2. Nó có nghĩa là chỉ rằng chuỗi t1 được lên lịch trước chủ đề 2, chưa thực sự bắt đầu. Hai phương pháp này lấy các phân số của mỗi thứ hai, vì vậy thực tế là chúng nằm trong chuỗi không thể được nhìn thấy bởi một người quan sát con người.

Thêm, các chuỗi Java là được lên lịch, tức là. được chỉ định là cuối cùng được thực hiện. Thậm chí nếu bạn có CPU đa lõi, bạn không chắc chắn rằng 1) các luồng chạy song song (các quy trình hệ thống khác có thể can thiệp) và 2) các luồng đều bắt đầu ngay sau khi phương thức Start() được gọi.

+1

Bạn không thể bắt đầu hai luồng cùng một lúc, nhưng bạn có thể đồng bộ hóa trong phương thức chạy. Tất nhiên, tất cả những gì bạn nói về việc thực hiện cuối cùng vẫn được áp dụng. Nhưng ít nhất bạn có thể phối hợp trình tự trong đó các phương thức chạy được thực hiện, trong trường hợp có một số phụ thuộc lẫn nhau. – Thilo

+0

Khi bạn đang xử lý các luồng và/hoặc nhiều CPU, thực sự không có thứ gì giống như 'cùng một lúc'. Bạn cần phải làm rõ câu hỏi của bạn. – EJP

1

Chúng bắt đầu ở "đóng" cùng một lúc. Vấn đề là mã của bạn không chặn tại t1.start().

Bạn có thể thấy điều này bằng cách thêm lệnh in ở đầu phương thức run() của lớp Meeting và một tuyên bố in khác ngay sau t2.start(). Một cái gì đó như thế này:

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 
Các vấn đề liên quan