Có điều gì đó kỳ lạ về việc triển khai BoundedExecutor
trong cuốn sách Java Concurrency in Practice.Java Concurrency trong Thực hành: điều kiện chủng tộc trong BoundedExecutor?
Đó là nghĩa vụ phải điều tiết công việc gửi tới Người thực thi bằng cách chặn luồng gửi khi có đủ chuỗi được xếp hàng hoặc chạy trong Trình thực thi.
này là việc thực hiện (sau khi thêm rethrow thiếu trong mệnh đề catch):
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command) throws InterruptedException, RejectedExecutionException {
semaphore.acquire();
try {
exec.execute(new Runnable() {
@Override public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
throw e;
}
}
Khi tôi nhanh chóng BoundedExecutor
với một Executors.newCachedThreadPool()
và ràng buộc của 4, tôi mong chờ số chủ đề khởi tạo bởi các hồ bơi lưu trữ thread không bao giờ vượt quá 4. Trong thực tế, tuy nhiên, nó không. Tôi đã nhận được chương trình thử nghiệm nhỏ này để tạo ra tối đa 11 chủ đề:
public static void main(String[] args) throws Exception {
class CountingThreadFactory implements ThreadFactory {
int count;
@Override public Thread newThread(Runnable r) {
++count;
return new Thread(r);
}
}
List<Integer> counts = new ArrayList<Integer>();
for (int n = 0; n < 100; ++n) {
CountingThreadFactory countingThreadFactory = new CountingThreadFactory();
ExecutorService exec = Executors.newCachedThreadPool(countingThreadFactory);
try {
BoundedExecutor be = new BoundedExecutor(exec, 4);
for (int i = 0; i < 20000; ++i) {
be.submitTask(new Runnable() {
@Override public void run() {}
});
}
} finally {
exec.shutdown();
}
counts.add(countingThreadFactory.count);
}
System.out.println(Collections.max(counts));
}
Tôi nghĩ rằng có một khung thời gian nhỏ giữa việc phát hành semaphore và kết thúc nhiệm vụ, trong đó một sợi khác có thể chứa giấy phép và gửi tác vụ trong khi chuỗi phát hành chưa hoàn thành. Nói cách khác, nó có một điều kiện chủng tộc.
Ai đó có thể xác nhận điều này không?
Tôi đã thêm 1ms Thread.sleep ngay sau semaphore.release() để xem mức độ tồi tệ hơn bao nhiêu: Tôi nhận được hơn 300 chuỗi được tạo. – toto2