Tôi đang sử dụng ThreadPoolExecutor
để chạy các tác vụ. Phần phụ trợ là SynchronousQueue
, vì vậy nếu người thực hiện đã hoàn thành một nhiệm vụ, nó sẽ ném RejectedExecutionException
. Dưới đây là một trường hợp thử nghiệm đơn giản:Bộ nhớ rò rỉ ThreadPoolExecutor của tôi có bị hỏng không?
public class ExecutorTest {
final static Worker worker = new Worker();
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
while (true) {
try {
executor.execute(worker);
}catch (RejectedExecutionException e) {
}
}
}
static class Worker implements Runnable {
private int i = 0;
private long start = System.currentTimeMillis();
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(++i + " " + (System.currentTimeMillis() - start));
} catch (InterruptedException ex) {
}
}
}
}
Các bahavious dự kiến là: Thực hiện các công nhân và sau khi ngủ trong một giây, in ra i (đại diện cho mức độ thường xuyên người lao động đã được thực hiện cho đến nay) và số lượng mili giây kể từ khi nhân viên đã được tạo. Vì vậy, tôi mong đợi:
1 1015
2 2015
3 3016
4 4017
này hoạt động tốt trong một thời gian, nhưng sau gần trên giờ:
2919 2922196
2920 2942951
2921 2990407
Vì vậy, khoảng thời gian giữa một thi nhân và người tiếp theo là 20 giây (2919-> 2920) và 38 giây (2920-> 2921) và vv. Mọi thứ trở nên cực kỳ chậm và jvm dành nhiều thời gian trong việc thu gom rác thải. Cuối cùng (sau một vài ngày) tôi chạy vào một OutOfMemoryError.
Tôi đang chạy ứng dụng này với -Xmx8M (Tôi cho rằng hiệu ứng xuất hiện sau này với nhiều khoảng trống hơn) trên JVM 1.7.0_07 của Oracle trên máy Linux 64 bit. Tôi đánh giá cao bất kỳ con trỏ, nhưng có lẽ tôi chỉ thiếu rõ ràng.
Có thể vùng heap bị tụt hậu với RejectedExecutionExceptions sau một thời gian (mặc dù tôi nghĩ các đối tượng ngoại lệ đã được sử dụng lại sau một thời gian)? Bạn đã cố gắng để hồ sơ ứng dụng của bạn? – assylias
@assylias Vâng, tôi đã lược tả các ứng dụng tất nhiên, nhưng ngu ngốc chỉ nhìn vào không gian heap và gc thế hệ còn sống sót. Tôi đang chạy profiler ngay bây giờ để kiểm tra, nhưng ngay từ cái nhìn đầu tiên RejctedExectutionExceptions dường như không phải là thủ phạm. Ngay cả khi họ đang có, tôi phải nắm bắt những ngoại lệ và không nên hết bộ nhớ vào cuối ngày, phải không? –
Điều đó sẽ giải thích số lượng GC tăng lên nhưng không phải là số ... – assylias