2010-09-19 31 views
5

Tôi bối rối về những điều sau đây:
Để sử dụng các chủ đề trong một chương trình Java, cách đơn giản nhất là mở rộng Thread class và thực hiện giao diện runnable (hoặc đơn giản là thực hiện runnable).
Để bắt đầu thực hiện luồng. chúng ta phải gọi phương thức start của Thread(), mà lần lượt gọi phương thức run() của luồng. Và do đó, chủ đề bắt đầu.
Phương thức start() (trừ khi tôi sai) phải được gọi chính xác và chỉ một lần cho mỗi chuỗi. Kết quả là, các thể hiện luồng không thể được tái sử dụng trừ khi bằng cách nào đó, phương thức chạy tự chạy trong một số vòng lặp vô hạn tạo điều kiện cho việc triển khai tùy chỉnh của việc hồi sinh luồng.
Bây giờ javadoc link text nóijava thread reusage thông qua executor

cuộc gọi để thực hiện sẽ sử dụng lại đề xây dựng trước đây nếu có

Tôi không hiểu làm thế nào điều này được thực hiện. Tôi cung cấp phương thức thực thi của phương thức thi hành chủ đề tùy chỉnh của tôi, ví dụ:

ExecutorService myCachedPool = Executors.newCachedThreadPool(); 
    myCachedPool.execute(new Runnable(){public void run(){ 
    //do something time consuming 

    }}); 

Làm cách nào để có thể sử dụng lại chuỗi tùy chỉnh này cho khung thực thi?
Người thực thi có được phép gọi phương thức start() nhiều hơn 1 lần trong khi chúng tôi không thể tham gia chương trình của chúng tôi không? Tôi có hiểu nhầm điều gì đó không?

Cảm ơn bạn.

Trả lời

4

Lưu ý rằng nó không phải là Executor gọi số start() - đó là ExecutorService. Và không, nó không gọi số start() hai lần. Nó không bắt đầu nhiệm vụ mà bạn cung cấp cho nó trực tiếp bằng cách sử dụng Thread.start() ... thay vào đó, nó bắt đầu một luồng mà biết về hàng đợi của luồng của công việc đó. Các chủ đề về cơ bản sẽ chờ đợi cho đến khi có một số công việc để làm, sau đó nhặt nó lên và thực hiện nó, trước khi trở lại chờ đợi. Vì vậy, mặc dù chuỗi thực hiện một số tác vụ, Thread.start() chỉ được gọi một lần.

EDIT: Đánh giá theo nhận xét, bạn có chút nhầm lẫn về sự khác biệt giữa một Runnable (là nhiệm vụ được thực thi) và Thread (đó là những gì thực thi tác vụ).

Cùng một luồng có thể thực hiện nhiều tác vụ. Đối với một ví dụ rất đơn giản không sử dụng một hồ bơi thread, xem xét việc này:

(Bỏ qua các vấn đề an toàn thread tiềm năng của việc sử dụng một List<T> từ nhiều chủ đề.)

Bạn có thể tạo một bó toàn bộ Runnable nhiệm vụ có khả năng làm những việc khác nhau, sau đó tạo một đơn MultiRunnable để chạy chúng lần lượt. Vượt qua trường hợp đó MultiRunnable vào hàm tạo Thread và sau đó khi bạn bắt đầu luồng, nó sẽ thực thi từng tác vụ chạy được ban đầu. cái đó có giúp ích không?

+0

@ Jon: Xin lỗi tôi bị mất bạn. Vì vậy, các chủ đề nội bộ của khuôn khổ được tái sử dụng và không phải là runnable tôi vượt qua như là đối số để thực hiện? Chủ đề của tôi mà tôi ủy nhiệm cho khung công tác sẽ được tái khởi tạo mỗi lần, nhưng bởi cùng một thể hiện của luồng nội bộ do khung công tác tạo ra? – Cratylus

+0

@ user384706: Có. Runnable của bạn * không phải là * một chủ đề - nó chỉ là một nhiệm vụ được thực hiện. Bạn cần phân biệt giữa hai người; chúng rất khác nhau. –

+0

@Jon: Cảm ơn bạn rất nhiều. Điều duy nhất tôi không chắc chắn là, lợi ích của việc sử dụng Executors.newCachedThreadPool(); Bởi vì nếu lớp của tôi thực hiện runnable (cho một nhiệm vụ) là tốn kém để được instantiated, nó sẽ không được tái sử dụng và cùng một thread của khuôn khổ, sẽ tiếp tục sử dụng các phiên bản mới của nhiệm vụ. Vì vậy, những gì tôi sẽ đạt được từ api này? Trừ khi khái niệm là mỗi lớp thực hiện runnable là tối thiểu. – Cratylus

5

Nó không gọi start() nhiều lần; thay vào đó Thread trong hồ bơi không bao giờ hoàn thành, nhưng chỉ còn sống --- chờ đợi. Mã nguồn có sẵn để tải xuống nếu bạn muốn xem mã nguồn.

Mỗi chủ đề trong nhóm luồng chỉ đơn giản là wait() để Người thực thi trao cho nó một Runnable mới, nhưng phương thức run() của chủ đề chưa hoàn thành. Nó chỉ đơn giản chờ đợi một Runnable mới được trao cho Executor.

+0

Vì vậy, bạn có nghĩa là trong javadoc, nơi nó nói "mà trước đó xây dựng chủ đề sẽ được tái sử dụng" nó không đề cập đến runnable tôi vượt qua để thực hiện, nhưng chủ đề nội bộ của khuôn khổ thực thi? Vì vậy, Runnable của tôi sẽ được tái khởi tạo bởi cùng một Thread of thread pool? Tôi đã hiểu những gì bạn đang nói? – Cratylus

+2

Runnable của bạn sẽ không được khôi phục. Ví dụ Runnable của bạn sẽ được trao cho một trong các Threads trong nhóm. Chuỗi đó có phương thức 'run()' riêng của nó, không phải là (không thể) được thay thế bằng phương thức 'run()' của Runnable. Phương thức run() của Thread sẽ gọi phương thức 'run()' của Runnable', và sau đó sau khi 'Runnable.run()' kết thúc, luồng sẽ kết thúc (có một số sổ sách kế toán sẽ phải được thực hiện). quay lại 'wait'ing. – jbindel

1

Để "bắt đầu" một chuỗi nhiều lần, hãy tạo runnable. Ví dụ:

//NO 
private class T extends Thread { //not necessary to implement runnable 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    a.start(); 
    a.start(); //NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO 
} 

Thay vào đó,

//Yes 
private class T implements Runnable { 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    new Thread(a).start(); 
    new Thread(a).start(); //YES YES YES 
} 

Nó cũng có thể làm điều này:

void someMethod(){ 
    final Runnable r = new Runnable(){ 
     public void run(){ 
      //... 
     } 
    }; 
    new Thread(r).start(); 
    new Thread(r).start(); 
} 
// r could also be a field of you class. 
Các vấn đề liên quan