Tôi đang xử lý một số mã thư viện của bên thứ ba có liên quan đến việc tạo các đối tượng đắt tiền và lưu chúng trong một Map
. Việc thực hiện hiện tại là cái gì đó nhưBản đồ chặn từng phím trong Java
lock.lock()
try {
Foo result = cache.get(key);
if (result == null) {
result = createFooExpensively(key);
cache.put(key, result);
}
return result;
} finally {
lock.unlock();
}
Rõ ràng đây không phải là thiết kế tốt nhất khi Foos
cho khác nhau keys
thể được tạo ra một cách độc lập.
Hack hiện tại của tôi là sử dụng một Map
của Futures
:
lock.lock();
Future<Foo> future;
try {
future = allFutures.get(key);
if (future == null) {
future = executorService.submit(new Callable<Foo>() {
public Foo call() {
return createFooExpensively(key);
}
});
allFutures.put(key, future);
}
} finally {
lock.unlock();
}
try {
return future.get();
} catch (InterruptedException e) {
throw new MyRuntimeException(e);
} catch (ExecutionException e) {
throw new MyRuntimeException(e);
}
Nhưng điều này dường như ... một chút hacky, vì hai lý do:
- Công việc được thực hiện trên một gộp tùy ý chủ đề. Tôi rất vui khi có công việc được thực hiện trên chuỗi đầu tiên cố gắng lấy khóa cụ thể đó, đặc biệt là kể từ khi nó sẽ bị chặn.
- Ngay cả khi
Map
được điền đầy đủ, chúng tôi vẫn xem qua sốFuture.get()
để nhận được kết quả. Tôi hy vọng điều này là khá rẻ, nhưng nó xấu xí.
Những gì tôi muốn là để thay thế cache
với một Map
rằng sẽ chặn được cho một chìa khóa cho đến khi chính mà có giá trị, nhưng cho phép khác được khi đó. Có bất kỳ điều như vậy tồn tại? Hoặc ai đó có một giải pháp thay thế sạch hơn cho Map
của Futures
?
Store đối tượng chủ chốt trong một 'ConcurrentHashMap' và khóa trên các đối tượng chính bản thân? Nếu các khóa là nội tại (int, 'String', v.v.) bọc chúng lại. –
Điều này gần giống như bạn muốn có một ổi ['sọc'] (http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/util/concurrent/Striped.html), loại hành vi như một bản đồ từ các đối tượng đến khóa. –