java - 如何确保一个方法只被多个线程调用一次?

标签 java multithreading oop concurrency

我有以下结构:

public void someMethod(){  
   //DO SOME STUFF
   try{  
    doSomeProcessing();  
   }  
   catch (Exception e){  
        loadSomeHeavyData();  
        doSomeProcessing();      
   }    
}  

someMethod 方法可能 被多个线程并发调用。 doSomeProcessing 可能 抛出异常(它在后端使用了一些可能过时的数据)。
如果抛出异常,则 loadSomeHeavyData(); 会执行一些耗时的任务,比如说“更新”所有当前数据,然后我可以调用 doSomeProcessing();。< br/> 问题:如何确保 loadSomeHeavyData(); 只被调用一次?如果我在 loadSomeHeavyData(); 的条目中放置一些原子标志,那么我无法确定何时应该清除它。
我该如何解决这个问题?请注意:我无法修改 doSomeProcessing();,因为它是一个外部 API,我正在使用装饰器模式来使用它。

最佳答案

您的 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();
    }
}

注意我的假设:

  • 您希望所有线程等待加载完成,以便它们可以使用更新后的数据第二次调用 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();
    }
}

关于java - 如何确保一个方法只被多个线程调用一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13356702/

相关文章:

java - 如何调用 JNA 到 VB.net ByRef 字符串函数

java - protected 构造函数和可访问性

c++ - UDP recvfrom 线程使用过多 CPU 资源

python - 如何在Python中调用不同类的函数

java - csvReader 跳过了 while 循环

java - Snakeyaml 将 yaml 转换为 pojo

c - 在多线程应用程序中用 C 语言制作目录树

c++ - Lambda 函数 C++ : Does capturing the index of a loop make a difference?

javascript - 在程序的范围内,首选放置 JavaScript 实用程序类的位置是什么?

数据库交互代码