2010-03-26 19 views
5

Tôi nghĩ đây là một kịch bản chung cho các ứng dụng Java đa luồng vì vậy tôi sẽ cố gắng mô tả nó ở đây.
Java Multithreaded App - cách hủy động các đối tượng tương lai

Trong ứng dụng Java của tôi, tôi có đối tượng Chính sách thi hành xác định một nhóm gồm 5 chủ đề.

ExecutorService threadExecutor = Executors.newFixedThreadPool(5); 

Một sendCallables phương pháp có trách nhiệm phân công một danh sách của Jobs đến Executor.
Tôi theo dõi Danh sách với một ObjectX. Bằng cách này tôi có thể tham khảo lại danh sách Futures nếu User muốn ngắt/hủy các Threads. Một cái gì đó như thế này:

Map<ObjectX, List<Future<String>>> map = new HashMap<ObjectX, Future<String>>(); 

public void sendCallables(ObjectX referenceObj, List<Callable<String>> list) { 
    ... 
    List<Future<String>> futureList = new ArrayList<Future<String>>(); 
    for(Callable<String> myCallableJob : list) { 
     Future<String> future = threadExecutor.submit(myCallableJob); 
     futureList.add(future); 
    } 
    ... 
    map.add(referenceObj, futureList); 
    ... 
} 

public void cancelFutures(ObjectX referenceObj) { 
    ... 
    List<Future<String>> list = map.get(referenceObj); 
    for(Future<String> future : list) { 
     future.cancel(); 
    } 
    map.remove(referenceObj); 
    .... 
} 

Cho đến nay rất tốt.

Hiện có các trường hợp khi không có cần thực hiện các tác vụ đã gửi nữa.
Trong những trường hợp này, quyết định hủy các nhiệm vụ sẽ được Ứng dụng đưa ra một cách thông minh/tự động.
Ví dụ về các trường hợp như vậy có thể được tìm thấy trong một Ứng dụng Web khi phiên của Người dùng hết hạn hoặc khi Luồng cụ thể (liên quan đến các tác vụ đã gửi) kết thúc trước khi tất cả các Lệnh được thực hiện.

Vì vậy, về cơ bản, tôi cần phải gọi cho cancelFutures (referenceObj) mọi lúc mà không có ý nghĩa gì cho ứng dụng của tôi tiếp tục thực hiện Công việc. Tôi đã xác định từng tình huống khi ứng dụng cần gọi nó.

Tôi tự hỏi nếu có cách tiếp cận tốt hơn để thực hiện việc này.

Tôi đã suy nghĩ trong một WeakHashMap để có thể dọn dẹp Bản đồ khi tham chiếuObj không được tham chiếu thêm bởi Ứng dụng nhưng điều này không ngăn Futures được thực thi vì tôi vẫn cần gọi .cancel() trên chúng (một loại eventHandler liên quan đến phương pháp WeakHashMap loại bỏ (Object)?)

Trả lời

3

Tôi nghĩ giải pháp bạn đang đề xuất là khá tốt. Nếu bạn thực sự, thực sự muốn lái xe hủy bỏ từ referenceObj nhận được rác thu thập sau đó bạn có thể sử dụng một sự kết hợp của WeakReference và ReferenceQueue.

Có một trong các trường được khai báo trong lớp trình trợ giúp thực thi của bạn.

ReferenceQueue<ObjectX> refQ = new ReferenceQueue<ObjectX>(); 

Làm điều này mỗi lần một lô công việc được gửi

new WeakReference<ObjectX>(referenceObj, refQ).enqueue(); 

Có một sợi mà chỉ chạy vòng lặp này mà kéo ra khỏi các đối tượng có trở nên yếu ớt-thể truy cập (có đủ điều kiện cho GC) và hủy bỏ tương lai/nhiệm vụ.

while (true) 
{ 
    // this blocks 
    ObjectX referenceObj = refQ.remove().get(); 
    cancelFutures(referenceObj); 
} 
+0

Ý tưởng là tốt miễn là bạn không giữ tham chiếu mạnh mẽ để tham chiếuObj ... – pgras

+0

cảm ơn Mike .. Tôi sẽ dùng thử – mickthompson

0

Nếu tôi hiểu chính xác vấn đề của bạn, bạn có nhiều loại hoạt động khác nhau và bạn không muốn kết hợp các hoạt động này với nhau chỉ vì chúng có thể bị hủy bỏ .

Với tôi, có vẻ như mỗi trường hợp cần hủy phải kích hoạt sự kiện. Trình xử lý sự kiện sẽ lắng nghe những sự kiện này và hủy liên quan Future.

Ví dụ về phiên của bạn - bạn sẽ có một lớp thực hiện javax.servlet.http.HttpSessionListner, phát hiện các tác vụ có liên quan cần hủy và kích hoạt sự kiện để hủy các tác vụ đó. Vì mọi thứ đều không đồng bộ, bạn sẽ không quan tâm liệu tác vụ đã hủy có được hoàn thành hay không nên không có gì bị mất.

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