Java: New thread to skip synchronised method if another thread already in it

Debapriyo Majumder :

Requirements

  1. I need to be able to trigger a (long running) job via a POST call and return immediately.

  2. Only one thread can run the job at one time.

  3. The job being an expensive one, I want all future triggers of this job to not do anything if one job is already in progress.

Code

@RestController
public class SomeTask {

    private SomeService someService;

    @Autowired
    public SomeTask(SomeService someService) {
        this.someService = someService;
    }

    @Async // requirement 1
    @RequestMapping(method = RequestMethod.POST, path = "/triggerJob")
    public void triggerJob() {
        expensiveLongRunningJob();
    }

    /**
     * Synchronized in order to restrict multiple invocations. // requirement 2
     *
     */
    private synchronized void expensiveLongRunningJob() { 
        someService.executedJob();
    }
}

Question

With the above code requirements 1 and 2 are satisfied. What is the best way to satisfy requirement 3 as well (have the new thread, created as a result of a POST call, skip the synchronised method and return immediately on failure to acquire a lock)?

Matt Timmermans :

Synchronization isn't the right tool for the job. You can do it like this:

@RestController
public class SomeTask {

    private SomeService someService;
    private final AtomicBoolean isTriggered = new AtomicBoolean();

    @Autowired
    public SomeTask(SomeService someService) {
        this.someService = someService;
    }

    @Async // requirement 1
    @RequestMapping(method = RequestMethod.POST, path = "/triggerJob")
    public void triggerJob() {
        if (!isTriggered.getAndSet(true)) {
            try {
                expensiveLongRunningJob();
            } finally {
                isTriggered.set(false);
            }
        }
    }

    /**
     * only runs once at a time, in the thread that sets isTriggered to true
     */
    private void expensiveLongRunningJob() { 
        someService.executedJob();
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=123227&siteId=1