How can I make sure a method is only called once by multiple threads?

后端 未结 5 1592
孤城傲影
孤城傲影 2020-12-17 17:46

I have the following structure:

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


        
5条回答
  •  悲哀的现实
    2020-12-17 18:26

    Your loadSomeHeavyData method could use a blocking mechanism to make all threads wait until it has finished its update, but only let one of them actually do the update:

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

    Note my assumptions:

    • you want all the threads to wait until the loading completes so they can call doSomeProcessing a second time with updated data
    • you only call loadSomeHeavyData once, ever - if not you will need to reset the flag and the CountdownLatch (which would then probably not be the most appropriate mechanism).

    EDIT

    Your latest comment indicates that you actually want to call loadSomeHeavyData more than once, just not more than once at a time.

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

提交回复
热议问题