2010-03-12 27 views
18

Trong chương trình của tôi, tôi đang tạo một số luồng trong phương thức main(). Dòng cuối cùng trong phương thức main là một lời gọi đến System.out.println(), mà tôi không muốn gọi cho đến khi tất cả các luồng đã chết. Tôi đã thử gọi Thread.join() trên mỗi thread tuy nhiên mà khối mỗi thread để họ thực hiện tuần tự thay vì song song.Làm cách nào để tạm dừng chính() cho đến khi tất cả các chuỗi khác đã chết?

Có cách nào để chặn luồng chính() cho đến khi tất cả các chuỗi khác đã hoàn thành việc thực thi không? Đây là phần có liên quan của mã của tôi:

public static void main(String[] args) { 

//some other initialization code 

//Make array of Thread objects 
Thread[] racecars = new Thread[numberOfRaceCars]; 

//Fill array with RaceCar objects 
for(int i=0; i<numberOfRaceCars; i++) { 
    racecars[i] = new RaceCar(laps, args[i]); 
} 

//Call start() on each Thread 
for(int i=0; i<numberOfRaceCars; i++) { 
    racecars[i].start(); 
    try { 
     racecars[i].join(); //This is where I tried to using join() 
          //It just blocks all other threads until the current        
          //thread finishes. 
    } catch(InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

//This is the line I want to execute after all other Threads have finished 
System.out.println("It's Over!"); 

} 

Cảm ơn các bạn trợ giúp!

Eric

Trả lời

39

Bạn bắt đầu chủ đề của bạn và ngay lập tức chờ đợi cho họ được hoàn thành (sử dụng join()). Thay vào đó, bạn nên làm như join() ngoài cho vòng lặp trong một cho vòng lặp, ví dụ .:

// start all threads 
for(int i=0; i<numberOfRaceCars; i++) { 
    racecars[i].start(); 
} 
// threads run... we could yield explicity to allow the other threads to execute 
// before we move on, all threads have to finish 
for(int i=0; i<numberOfRaceCars; i++) { 
    racecars[i].join(); // TODO Exception handling 
} 
// now we can print 
System.out.println("It's over!"); 
+0

Đẹp, điều đó đã làm việc rất đẹp! Cảm ơn! – ericso

+3

Đây rõ ràng là con đường phù hợp để đi. Tôi không thể tin các câu trả lời khác ủng hộ việc sử dụng wait() và notify() và các rào cản đã được upvoted: chúng quá phức tạp cho tình huống này. –

+0

@AdrianPronk: Đó là vẻ đẹp của các ý kiến ​​khác nhau. – Thomas

2

Bạn có thể wait() trong chủ đề chính của bạn và có tất cả chủ đề ra notifyAll() khi họ đã hoàn tất. Sau đó, mỗi lần chủ đề chính của bạn được đánh thức theo cách đó, nó có thể kiểm tra xem có ít nhất một luồng vẫn còn sống trong trường hợp đó bạn wait() một số khác không.

+0

tôi vẫn đang học lập trình Java vì vậy tôi không hoàn toàn hiểu được đồng bộ hóa và đối tượng màn hình được nêu ra. Tôi sẽ điều tra điều này. Cảm ơn! – ericso

+1

@thechiman - nếu bạn có một số thời gian rảnh rỗi trong tay, bạn cũng có thể muốn nghiên cứu gói java.util.concurrent cung cấp một số cách khá mạnh mẽ để đồng thời vượt quá "cấp thấp" Chủ đề. – Thomas

+0

Tôi cũng sẽ kiểm tra điều đó. Cảm ơn. – ericso

0

Bạn có thể làm cho dòng cuối cùng ở trong một "giám sát" chủ đề. Nó sẽ kiểm tra tất cả các thường xuyên như vậy mà nó là chỉ chạy thread và một số hoàn thành nhà nước == true và sau đó có thể cháy nếu nó được. Sau đó, nó có thể làm những việc khác hơn là chỉ println

1

Bạn có thể sử dụng phương thức kết hợp. Tham khảo tài liệu here

+0

, anh ta đã sử dụng join. – middus

5

Bạn có thể chia sẻ một đối tượng CyclicBarrier trong RaceCar của bạn và chủ đề chính của bạn, và có RaceCar đề gọi await() như ngay khi chúng được thực hiện với nhiệm vụ của họ. Xây dựng các rào cản với số lượng RaceCar chủ đề cộng với một (cho chủ đề chính). Chuỗi chính sẽ tiếp tục khi tất cả RaceCar giây kết thúc. Xem http://java.sun.com/javase/6/docs/api/java/util/concurrent/CyclicBarrier.html

Cụ thể, xây dựng một CyclicBarrier trong thread chính, và thêm một cuộc gọi barrier.await() trong lớp RaceCar của bạn ngay trước khi run() thoát phương pháp, cũng bổ sung một ghé barrier.await() trước System.out.println() cuộc gọi trong chủ đề chính của bạn.

+0

Tôi cũng sẽ kiểm tra điều này, nhờ sự giúp đỡ. – ericso

+0

Chỉ cần thấy rằng Java có một lớp gọi là "java.util.concurrent.CountDownLatch" dành riêng cho vấn đề như vậy, hoạt động tương tự như rào chắn, nhưng cho phép các chuỗi xe hoàn thành thoát ngay lập tức khi chúng được thực hiện bằng cách cung cấp một phương thức "countDown()". –

+0

@ the-banana-king: +1 ... Lợi thế của các rào cản tuần hoàn và/hoặc đếm chốt vv là chúng cũng được biết đến kỹ thuật đồng thời và * không * Java idiosynchrasies đòi hỏi kiến ​​thức sâu sắc về các đặc tính Java không quan tâm. Những cuốn sách như * "Java Concurrency in Practice" * khuyên bạn nên tránh các chi tiết ở mức độ thấp (Java) và đi đến các giải pháp/trừu tượng mức cao hơn. – SyntaxT3rr0r

1

Bạn có thể thêm móc tắt cho thông báo "Đã kết thúc". Bằng cách này, nó sẽ được tạo ra khi chương trình kết thúc và bạn không phải đợi từng luồng.

0

đơn giản nhất cách

while (Thread.activeCount() > 1) { 
} 

Tôi biết nó chặn chủ đề chính ... nhưng nó hoạt động một cách hoàn hảo!

0

Hãy thử ví dụ này:

public class JoinTest extends Thread { 

    public static void main(String[] args) 
    { 
     JoinTest t = new JoinTest(); 
     t.start(); 

     try { 

      t.join(); 
      int i = 0; 
      while(i<5) 
      { 
       System.out.println("parent thread is running......" +i++); 
      } 

     } catch (Exception e) { 
      // TODO: handle exception 
     } 


    } 


    public void run() 
    { 

     try { 

      int i =0; 
      while(i<5) 
      { 
       System.out.println("child thread running ........." +i++); 
      } 

     } catch (Exception e) { 
      // TODO: handle exception 
     } 
    } 
} 
+0

Vui lòng giải thích lý do tại sao tính năng này hoạt động, xem [cách trả lời] (http://stackoverflow.com/help/how-to-answer). – agold

0

Bạn có các tùy chọn tốt hơn nếu bạn đi cho ExecutorService hoặc ThreadPoolExecutor khuôn khổ.

  1. invokeAll

    Thực hiện những nhiệm vụ nhất định, trả lại một danh sách các Futures giữ tình trạng và kết quả khi tất cả hoàn toàn của họ. Future.isDone() là đúng cho mỗi phần tử của danh sách được trả về. Lưu ý rằng một tác vụ hoàn thành có thể đã chấm dứt bình thường hoặc bằng cách ném một ngoại lệ. Kết quả của phương pháp này không xác định nếu bộ sưu tập đã cho được sửa đổi trong khi thao tác này đang được tiến hành. Thông số Loại:

  2. : Initialize CountDownLatch with counter as number of threads. Sử dụng các API countDown()await() và đợi bộ đếm trở thành 0.

tài liệu tham khảo thêm:

How to use invokeAll() to let all thread pool do their task?

How is CountDownLatch used in Java Multithreading?

Các vấn đề liên quan