Java: nuevo hilo para saltar método sincronizado si otro hilo ya en ella

Debapriyo Majumder:

requisitos

  1. Tengo que ser capaz de desencadenar un trabajo (de larga duración) a través de una llamada POST y volver inmediatamente.

  2. Sólo un hilo puede ejecutar la tarea a la vez.

  3. El trabajo de ser una cara, quiero todos los disparadores futuras de este trabajo para no hacer nada si un puesto de trabajo ya está en marcha.

Código

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

Pregunta

Con los requisitos de los códigos anteriores 1 y 2 son satisfechos. ¿Cuál es la mejor manera de satisfacer el requisito 3, así (que el nuevo hilo, creado como resultado de una llamada POST, saltarse el método sincronizado y volver de inmediato en caso de fallo adquirir un bloqueo)?

Matthew Timmermans:

La sincronización no es la herramienta adecuada para el trabajo. Puede hacerlo de esta manera:

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

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=228118&siteId=1
Recomendado
Clasificación