2009-07-31 38 views
9

Theo đồng thời Java Goetz của Java trong thực tế JVM không thể thoát cho đến khi tất cả các chủ đề (nondaemon) đã chấm dứt, do đó, không đóng một Executor có thể ngăn chặn JVM thoát khỏi.Làm thế nào để tắt tất cả các Executors khi bỏ một ứng dụng?

I.e. System.exit (0) không nhất thiết phải hoạt động như mong đợi nếu có Executors xung quanh. Có vẻ như cần thiết để đặt một số loại

public void stop() { exec.shutdown() } 

phương thức cho tất cả các lớp có chứa Executors, sau đó gọi cho chúng khi ứng dụng sắp kết thúc. Đây có phải là cách duy nhất, hoặc là có một số loại phím tắt để tắt tất cả các Executors?

+0

Tôi đã nhầm lẫn Executor with Runnable. Tôi đã xóa câu trả lời của tôi vì nó không có ý nghĩa nhiều. @skaffman có phiếu bầu của tôi. –

Trả lời

14

Không có lối tắt nào để thực hiện tất cả, không. Ngoài ra, có thể bạn nên gọi shutdownNow() thay vì shutdown(), nếu không bạn có thể chờ một lúc.

Những gì bạn có thể làm, tôi giả sử, là khi bạn tạo Executor, hãy đăng ký nó ở vị trí trung tâm. Sau đó, khi tắt, chỉ cần gọi shutdown() trên đối tượng trung tâm đó, từ đó có thể chấm dứt từng người thực thi đã đăng ký.

Nếu bạn sử dụng Spring, thì bạn có thể tận dụng lợi thế của các hạt của nhà máy tạo và quản lý các Executors cho bạn. Điều đó bao gồm tắt chúng một cách duyên dáng khi ứng dụng thoát và giúp bạn tự quản lý chúng.

+0

Đăng ký trung tâm có vẻ là một lựa chọn hợp lý. Hài hước rằng java.util.concurrent không bao gồm như vậy. –

+0

Nó cũng là một sự xấu hổ rằng Executors chỉ là một loạt các statics, mà làm cho nó khó khăn để ẩn nó đằng sau một giao diện đăng ký mà không nhân đôi vài chục chữ ký phương pháp. – skaffman

+0

Tôi cũng đang đối mặt với vấn đề tương tự. Tôi không rõ ràng bằng cách sử dụng ScheduledThreadPoolExecutor. Vì vậy, tôi không có bất kỳ tham chiếu trung tâm nào giống nhau. Trong trường hợp này, làm thế nào để truy cập các threadpools này? Tôi đang cố gắng để tắt chúng một cách duyên dáng trong phương thức ContextDestroyed – DecKno

0

Có thể anh ta muốn nói rằng JVM không thể tự mình dừng lại cho đến khi chuỗi nondaemon kết thúc. Nó giống như chạy một lớp đơn giản từ lệnh như java SomeClass và sau khi thực thi phương thức main JVM dừng lại.

System.exit là lệnh chấm dứt JVM, ngay cả khi chuỗi chủ đề đang chạy JVM sẽ tắt.

+1

Như Goetz đã viết, * nondaemon * chủ đề có thể ngăn chặn JVM từ thoát. Thực ra tôi đã trải nghiệm điều này. Trình gỡ lỗi cho thấy ứng dụng có thể bị kẹt vào Hệ thống.thoát (0) vô hạn, nhưng nó có vẻ là hành vi không xác định. Thông thường nó không bị kẹt, nhưng đôi khi nó có. –

5

Bạn cũng có thể cung cấp việc triển khai ThreadFactory đánh dấu các chủ đề đã tạo thành các chuỗi daemon. Tôi thích một cơ chế tắt máy sạch (với các phương pháp vòng đời) nhưng có những trường hợp bạn không cần đảm bảo về trạng thái/hoàn thành nhiệm vụ chưa hoàn thành khi điều này có thể phù hợp.

+0

Cảm ơn bạn đã chỉ ra tùy chọn này. Trên thực tế một số người thực thi của tôi nên là chủ đề daemon, họ chỉ xảy ra được những người không daemon bởi vì đó là những gì Executors.newXXXExecutor(): s làm theo mặc định. –

7

Theo mặc định, Trình thực thi sẽ chỉ tạo chuỗi không phải daemon. Bạn có thể ghi đè điều đó bằng cách cung cấp cho Executor với ThreadFactory của riêng bạn. Dưới đây là một ví dụ:

class DaemonThreadFactory implements ThreadFactory { 
    public Thread newThread(Runnable r) { 
    Thread t = new Thread(r); 
    t.setDaemon(true); 
    return t; 
    } 
} 

Hãy thận trọng, tuy nhiên, vì JVM sẽ thoát ngay lập tức ngay cả khi những chủ đề đang bận rộn làm công việc hữu ích!

8

Trang trí người thi hành với com.google.common.util.concurrent.MoreExecutors#getExitingExecutorService

@Beta 
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, 
             long terminationTimeout, 
             TimeUnit timeUnit) 

Chuyển đổi ThreadPoolExecutor đưa vào một ExecutorService mà thoát khi ứng dụng hoàn tất. Nó làm như vậy bằng cách sử dụng các chủ đề daemon và thêm một hook shutdown để chờ đợi cho hoàn thành của họ.

Đây là chủ yếu cho các hồ bơi cố định. Xem Executors.newFixedThreadPool (int).

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