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

}
Semaforos en Java

Mas regex

"^(?:[0-9]{1,9}\,[0-9]{1,2} | [0-9]{1,9})$"

Validacion del siguiente numero:
– en la parte entera de 1 a 9 digitos, empezando por el 0.
– en la parte decimal, de 0 a dos digitos.
– se permite solo parte entera.

(?:(\d|[1-9]\d|100) | ((\d|[1-9]\d|99)\,[0-9]{1,2}) | (100,00))$

Validacion del siguiente numero:
– Número entre 0 y 100,00
– los numeros dentro de este rango pueden contener 2 decimales separados por una coma.

^d+[,]?d+$

Validacion de un numero con coma(,) como separador de decimales. Puede o no contener coma

Editor para probar tus regex.
Editor para probar tus javascripts.

Mas regex

Chocolatey

Chocolatey es un pograma para instalar programas en windows a través de la consola, como brew para mac o apt-get install en linux.

Bueno pues de la manera normal no he podido, por el p*** proxy, así que he tenido que configurarlo. He creado un recordatorio en mi GitHub.

Por ejemplo me instala el editor atom y el apm (para instalar plugins a través de consola).

choco install atom

Aquí todos los programas que puedes instalar.
¿para que es bueno?, por ejemplo para cuando formateas el equipo crear un script que te instale todos los programas frecuentes. Como este script.

Chocolatey

atom.io

Este editor creado por la gente de GitHub, tiene un potencial enorme. Sobre todo por la cantidad de plugins de la que dispone. Y eso que solo esta empezando. Ya se puede descargar, ha salido de la beta privada.

A mi personalmente me ha dado varios errores:

  • En su instalacion, al terminar no me dejaba escribir en el editor. Un reinicio del ordenador lo arregló.
  • He tenido que volver a instalar pues daba un error fuerte

Los plugins se pueden instalar desde la consola con anpm, imitando al npm de node.js. De hecho son hermanos en su arquitectura.

Tienen cosas que pulir pero si me lo puedo instalar en el Windows del trabajo…

atom.io

EditorConfig

En estas vacaciones he podido probar alguna herramienta nueva como atom, y he descubierto un movimiento que es interesante, indicar al editor, mediante un fichero, la configuración que quieres que tenga ese proyecto. Configuracion como el tipo de letra, codificacion, etc.

Han hecho plugins para los editores de JetBrains(IntellJ Idea), Notepad++, JEdit, Vim, pero para eclipse todavia no esta.

editorconfig.org

EditorConfig

Mathias’s dotfiles

Esta persona Mathias, ha publicado en github, sus ficheros .* de configuracion de diferentes herramientas:

  • fichero de configuracion de gitconfig
  • fichero de configuracion de basrc
  • fichero de configuracion de vim
  • fichero de configuracion de wget

De momento lleva algo mas de 9.000 «stars» en GitHub. la verdad es que la consola a colores esta muy bien, asi como los alias. Aunque no no me voy a acordar de todos.

Mathias’s dotfiles

brew + cask

Cuando vas a formatear tu mac, es útil tener un script que te instale los programas habituales, en lugar de ir a la página web, descargarlos y guardarlos en Aplicaciones.

Dentro de brew, hay una aplicación que se encarga de instalar programas como Google Chrome o el navegador anónimo Tor. Se llama cask.

En este enlace esta la informacion de como se usa.

Un ejemplo de script de instalacion de varios programas.

brew + cask