2012-03-01 34 views
6

Tôi có một số lượng lớn các tác vụ cần thực hiện với multithreading.Cách quản lý bộ nhớ khi sử dụng ExecutorService?

Tôi sử dụng số ExecutorService để gửi rất nhiều Callable objects và mỗi Callable object chứa một số resource cần thiết để thực thi.

Vấn đề

Những nhiệm vụ này rất nhiều rằng Callable objects trình ExecutorService chiếm quá nhiều bộ nhớ thì heap đang cạn kiệt.

Tôi muốn biết, khi nào thì JVM giải phóng dung lượng cho các Callable objects này?

Làm điều này ngay lập tức sau khi công việc được thực hiện và làm thế nào tôi có thể quản lý bộ nhớ được sử dụng cho ExecutorService?

Tôi muốn kiểm soát việc gửi đến ExecutorService, ví dụ: khi bộ nhớ không đủ thì chặn việc gửi sẽ sử dụng một số tác vụ đã hoàn thành và dung lượng trống. Có thể nó?


Toàn bộ mã quá compliticated, tôi sẽ đính kèm khung chính của mã của tôi.

public class MyCallable implements Callable<Result> { 

    ... // Some members 

    public MyCallable(...) { 
    ... 
    } 

    @Override 
    public Result call() throws Exception { 
    ... // Doing the task 
    } 
} 

class MyFutureTask extends FutureTask<Result> { 

    ... // Some members 

    public MyFutureTask(...) { 
    super(new MyCallable(...)); 
    } 

    @Override 
    public void done() { 
    Result result = get(); 
    ... // Something to do immediately after the task is done 
    } 
} 

// Here is the code to add tasks 
ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize); 
while (...) { 
    ... // Reading some data from files 
    executor.submit(new MatchFutureTask(...)); 
} 
executor.shutdown(); 
+0

Một câu trả lời cho vấn đề của bạn có thể được đưa ra nếu bạn thêm một đoạn mã. Bạn đang sử dụng loại dịch vụ thi hành nào? Có nghĩa là gì (nghĩa là bao nhiêu)? –

+0

PS: Tôi có cảm giác rằng bạn đang phải đối mặt với vấn đề rò rỉ bộ nhớ (tôi đoán trong một số phần khác của ứng dụng bạn đang giữ tham chiếu đến Callables) chứ không phải vấn đề về dịch vụ thi hành. –

+0

@AlexCalugarescu Tôi sử dụng Executors.newFixedThreadPool() để tạo ExecuteService, vì vậy nó phải là ThreadPoolExecutor. Và "nhiều" có nghĩa là, tệp văn bản gốc có dung lượng lớn hơn 3GB, tôi đọc nó và bí mật với một số đối tượng để lưu trữ trong Callables, vì vậy tôi nghĩ rằng nó thực sự quá nhiều. – Auguste

Trả lời

3

Phương thức Runtime.getRuntime().freeMemory() sẽ cho bạn biết số lượng bộ nhớ miễn phí mà JVM có. Bạn có thể viết thực thi ThreadFactory để kiểm tra giá trị này trước khi tạo chuỗi mới.

+0

không phải là một vấn đề tôi đang phải đối mặt nhưng câu trả lời tuyệt vời +1. – Shahzeb

6

Nếu bạn đang sử dụng ExecutorService, bạn phải chuyển một BlockingQueue vào hàm tạo, phải không? Tôi giả sử bạn đang sử dụng một ThreadPoolExecutor. Sử dụng một ArrayBlockingQueue với một công suất cố định, và vượt qua ThreadPoolExecutor.CallerRunsPolicy đến constructor ThreadPoolExecutor. Điều này sẽ khá hiệu quả giới hạn tỷ lệ gửi của bạn nếu bạn đặt tối đaPoolSize thành một số giá trị hợp lý.

Để trả lời câu hỏi đầu tiên của bạn, VM sẽ giải phóng bộ nhớ "tại một thời điểm sau" không còn bất kỳ tham chiếu nào đến đối tượng. Nếu Callable là khép kín trong điều khoản của nhà nước, một khi nó được thực hiện xong, VM nên thu thập rác trước khi cho bạn một lỗi bộ nhớ.

+0

Vâng, tôi chỉ sử dụng Executors.newFixedThreadPool() để tạo ExecuteService, vì vậy tôi đã không vượt qua một BlockingQueue. BlockingQueue làm gì? – Auguste

+0

Một BlockingQueue sẽ chỉ cho phép một số lượng nhiệm vụ cụ thể được xếp hàng đợi trong người thi hành. Executors.newFixedThreadPool() sẽ cho phép một số nhiệm vụ không giới hạn. – brettw

+2

Tôi nghĩ rằng tôi giải quyết nó.Tôi thay đổi để tạo ra các đối tượng ThreadPoolExecutor của bản thân mình, mà thực sự có thể kiểm soát kích thước của hàng đợi nhiệm vụ chờ đợi. Cảm ơn nhiều! – Auguste

2

Có vẻ rằng việc sử dụng Executors.newCachedThreadPool() giảm bộ nhớ bằng 30% - 60%

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