当前位置: 首页 > 面试题库 >

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

左丘繁
2023-03-14
问题内容

我有以下结构:

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

该方法someMethod 可以 被许多线程同时调用。该doSomeProcessing
抛出异常(它在后台,可能成为过时的使用一些数据)。
如果引发异常,则loadSomeHeavyData();执行一些耗时的任务,比如说“更新”所有当前数据,并且我可以调用doSomeProcessing();
问题: 如何确保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();
    }
}


 类似资料:
  • 我有一个层,称为,另一个称为。我想知道我是否可以强制执行一条规则,上面写着: 在参数列表包含名为foo的参数的服务层中的任何公共类的任何公共方法中,断言它从权限层调用方法(理想情况下,确保在服务层中的任何其他方法之前调用该方法)。 ArchUnit可以这样做吗?

  • 我试图用一个自定义对象创建一个新线程,然后从主线程调用这个自定义对象方法。其思想是,主线程可以继续执行其他任务,而自定义对象可以继续在第二个线程中工作: 输出为: 它应该更像这样: 所以主线程被阻塞,直到方法完成。主线程是否在第二个线程中等待完成(作为返回类型为空,我认为情况不会如此)?还是在第一个线程中执行,因此阻塞了它? 我知道使用下面的代码,我可以在另一个线程中执行,但它每次都会从头开始创建

  • 以下是问题陈述: 编写一个java程序,使用线程计算前25个素数,并计算前50个斐波那契数。将计算斐波那契数的线程的优先级设置为8,将另一个设置为5。在计算了30个斐波那契数之后,让这个线程进入睡眠状态,开始计算素数。计算完25个素数后,继续斐波那契数计算。 我的代码: 我本以为当斐波那契线停止时,其余的素数会被打印出来,但那没有发生,这背后的原因可能是什么?

  • 问题内容: 在Java中使用Mockito如何验证某个方法仅被调用一次且其确切参数忽略对其他方法的调用? 样例代码: 在本节中应该做什么? 已经尝试失败: 不。它不允许调用其他方法,例如。 不。没有考虑到我们允许一个呼叫。 问题答案: 第一个检查预期的参数化呼叫,第二个检查根本没有一个呼叫。

  • 问题内容: 我有一个使用两个线程的程序。我已经在两个线程中都设置了断点。在gdb下运行程序时,我想在线程之间切换并使其运行。(线程t1是活动的并且正在运行,线程t2;在断点处暂停时。我想停止T1的运行并运行T2)。 有什么办法可以安排gdb中的线程? 问题答案: 如果您使用的是GDB 7或更高版本,请尝试“不间断模式”。 http://sourceware.org/gdb/current/onli

  • 问题内容: 前几天,当我的程序尝试使用在另一个线程上创建的处理程序向该线程发送消息时,抛出NullPointerException。尽管调用线程已经在另一个线程上调用了start,但是尚未创建另一个线程创建的处理程序,或者该调用程序尚未看到该线程。这种情况很少发生。几乎每个测试运行都不会获得异常。 我想知道最好的方法是以最小的复杂性和性能损失来确保避免此问题。该程序是一款游戏,对性能非常敏感,尤其