Semaforos en Java


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

}
Anuncios
Semaforos en Java