Jim*_*Jim 11 java oop concurrency multithreading
我有以下结构:
public void someMethod(){
//DO SOME STUFF
try{
doSomeProcessing();
}
catch (Exception e){
loadSomeHeavyData();
doSomeProcessing();
}
}
Run Code Online (Sandbox Code Playgroud)
该方法someMethod 可以由许多线程同时调用.该doSomeProcessing 会抛出异常(它在后台,可能成为过时的使用一些数据).
如果抛出异常然后loadSomeHeavyData();做一些耗时的任务,让我们说"更新"所有当前数据,我可以调用doSomeProcessing();.
问题:如何确保loadSomeHeavyData();只调用一次?如果我在条目中放入一些原子标志,loadSomeHeavyData();那么我不能确定何时应该清除它.
我怎么解决这个问题?只是注意:我无法修改,doSomeProcessing();因为它是一个外部API,我使用装饰模式来使用它.
ass*_*ias 11
您的loadSomeHeavyData方法可以使用阻塞机制使所有线程等到它完成更新,但只允许其中一个实际执行更新:
private final AtomicBoolean updateStarted = new AtomicBoolean();
private final CountDownLatch updateFinished = new CountDownLatch(1);
public void loadSomeHeavyData() {
if (updateStarted.compareAndSet(false, true)) {
//do the loading
updateFinished.countDown();
} else {
//update already running, wait
updateFinished.await();
}
}
Run Code Online (Sandbox Code Playgroud)
请注意我的假设:
doSomeProcessing第二次调用更新的数据loadSomeHeavyData一次 - 如果不是,你将需要重置标志和CountdownLatch(这可能不是最合适的机制).编辑
您的最新评论表明您实际上想要loadSomeHeavyData多次拨打电话,一次只能拨打一次.
private final Semaphore updatePermit = new Semaphore(1);
public void loadSomeHeavyData() {
if (updatePermit.tryAcquire()) {
//do the loading and release updatePermit when done
updatePermit.release();
} else {
//update already running, wait
updatePermit.acquire();
//release the permit immediately
updatePermit.release();
}
}
Run Code Online (Sandbox Code Playgroud)