Me había construido una clase que era un semáforo de procesos. Cuando me he preguntado, lo que suelo preguntarme: «¿y esto, no lo habrá hecho otro ya?». Y la respuesta es si, existen desde hace ni se sabe .
java.util.concurrent.Semaphore
y se pueden instanciar desde Spring.
<bean id="semaphoreJobA" class="java.util.concurrent.Semaphore"> <constructor-arg index="0" type="int" value="1" /> <constructor-arg index="1" type="boolean" value="true" /> <!-- permits - the initial number of permits available. This value may be negative, in which case releases must occur before any acquires will be granted. --> <!-- fair - true if this semaphore will guarantee first-in first-out granting of permits under contention, else false --> </bean>
Luego en tu clase, los invocas y les dejas hacer su magia.
@Override public void execute(JobExecutionContext context) throws JobExecutionException { // Invoco a Spring, por que estoy ejecutando fuera de su contexto. Semaphore semaphoreJobA = (Semaphore) SpringApplicationContext.getBean("semaphoreJobA"); String whoiam = String.valueOf(this.hashCode()); try{ LOGGER.info("t"+whoiam +"-"+ taskType.name()+"t Pregunto al semaforo si puedo continuar"); semaphoreJobA.acquire(); LOGGER.info("t"+whoiam +"-"+ taskType.name()+"t He pasado, ejecutando tarea..."); doTask(whoiam); }catch(Exception e){ LOGGER.error("t"+whoiam +"-"+ taskType.name()+"t Error: ", e); JobExecutionException e2 = new JobExecutionException(e); e2.setStackTrace(e.getStackTrace()); throw e2; }finally{ semaphoreJobA.release(); } }
¿Como era mi clase?, ya probada y testeada. Con muchas mejoras por hacer…
package net.pp.jm.scheduler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Cualquiera puede coger la vez no importa el orden de llegada sino el mas rapido en cuanto este vacio el semaforo * * @author josemanuel.prietopalacios.net * */ public class Semaforo { private static final Logger LOGGER = LoggerFactory.getLogger(Semaforo.class); // estos podrian ser semaforos del API Java... int hashCodeTask1; int hashCodeTask2; int hashCodeTask3; int hashCodeTask4; private boolean finish_method_run; public synchronized boolean running(TaskType tarea, int hashCode){ LOGGER.info(hashCode +"-"+ tarea.name() + " solicitud de ejecucion"); // Aqui se puede usar un Lock: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html if(finish_method_run){ while(!finish_method_run){ try { Thread.sleep(100); } catch (InterruptedException e) { LOGGER.error("ERROR: ", e); } } } if(ican(tarea, hashCode)){ switch(tarea){ case tarea1: hashCodeTask1 = hashCode; break; case tarea2: hashCodeTask2 = hashCode; break; case tarea3: hashCodeTask3 = hashCode; break; case tarea4: hashCodeTask4 = hashCode; break; } LOGGER.info(hashCode +"-"+ tarea.name() + " running..."); return true; }else{ return false; } } private boolean ican(TaskType tarea, int hashCode){ boolean ican = false; switch(tarea){ case tarea1: ican = (hashCodeTask1 != 0) ? false : true; break; case tarea2: ican = (hashCodeTask2 != 0) ? false : true; break; case tarea3: ican = (hashCodeTask3 != 0) ? false : true; break; case tarea4: ican = (hashCodeTask4 != 0) ? false : true; break; } return ican; } public synchronized void finish(TaskType tarea, int hashCode){ finish_method_run = true; switch(tarea){ case tarea1: hashCodeTask1 = 0; break; case tarea2: hashCodeTask2 = 0; break; case tarea3: hashCodeTask3 = 0; break; case tarea4: hashCodeTask4 = 0; break; } LOGGER.info(hashCode +"-"+ tarea.name() + " finish"); finish_method_run = false; } }