Tôi đang tạo một giao diện để thực thi đồng thời, trong khi trừu tượng hóa các chi tiết đồng bộ hóa (Để hoán đổi để thực hiện phân tán khi cần). Tôi đã tạo một triển khai jvm duy nhất cho phép các chuỗi được sử dụng làm mutex bằng cách lưu trữ chúng trong một bản đồ để đảm bảo một tham chiếu được sử dụng, ngay cả khi các chuỗi tham chiếu khác nhau được truyền vào. ngạc nhiên khi thấy rằng thử nghiệm đã cho thấy số lượng tham chiếu không bao giờ giảm. Tôi giả sử sử dụng WeakValues () sẽ là đủ để ngăn chặn rò rỉ bộ nhớ, nhưng có vẻ như đó không phải là trường hợp. Bất cứ ai có thể chỉ ra những gì có thể gây ra rò rỉ này?Rò rỉ bộ nhớ trong thông tin bản đồ yếu cho phương thức đã đồng bộ
public class SynchronousMethodExecutorSynchronizedImpl implements ISynchronousMethodExecutor {
// mutex map to provide string references
final Map<String, String> mutexMap = new MapMaker()
.weakValues()
.makeComputingMap(
new Function<String, String>() {
@Override
public String apply(String id) {
return id;
}
});
@Override
public Object doSynchronousMethod(String domain, String id, ISynchronousMethod synchronousMethod) {
synchronized(mutexMap.get(domain + "." + id))
{
return synchronousMethod.execute();
}
}
}
Đây là bài kiểm tra đó là thất bại vào sự khẳng định cuối cùng:
public class SynchronousMethodExecutorSynchronizedImplTest extends TestCase {
int counter;
SynchronousMethodExecutorSynchronizedImpl methodExecutor;
@Override
public void before() throws Exception {
super.before();
methodExecutor = new SynchronousMethodExecutorSynchronizedImpl();
}
@Test
public void concurrentExecute() throws InterruptedException {
assertEquals(0, counter);
for(int i=0; i<1000; i++)
getConcurrentExecutorThread().start();
// wait for threads to complete
Thread.sleep(1000);
assertEquals(1, methodExecutor.mutexMap.size());
try
{
final List<long[]> infiniteList = new LinkedList<long[]>();
for(long i = Long.MIN_VALUE; i < Long.MAX_VALUE; i++)
infiniteList.add(new long[102400]);
fail("An OutOfMemoryError should be thrown");
}
catch(OutOfMemoryError e)
{
}
assertEquals(2000, counter);
assertEquals(0, methodExecutor.mutexMap.size());
}
// synchronous method
private ISynchronousMethod method = new ISynchronousMethod() {
@Override
public Object execute() {
counter++;
return null;
}
};
/**
* Executes a line of code.
*
* @return Thread
*/
private Thread getConcurrentExecutorThread() {
return new Thread() {
@Override
public void run() {
methodExecutor.doSynchronousMethod("TEST", "1", method);
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
}
methodExecutor.doSynchronousMethod("TEST", new String("1"), method);
}
};
}
}
khẳng định cuối cùng này là những gì phá vỡ kiểm tra: assertEquals (0 , methodExecutor.mutexMap.size());
Rất tốt thưa ngài! Tôi đã thay đổi nó để lưu trữ một String mới (id), và nó hoạt động như một sự quyến rũ! –
Tại sao bạn nói rằng bản đồ sẽ không luôn trống? –
@Anthony: Tôi có thể sai, nhưng tôi không nghĩ có bất kỳ sự đảm bảo nào về thời điểm các tham chiếu yếu sẽ bị xóa. – ColinD