Comenzamos una serie de posts relacionados con la concurrencia en Java y la ejecución de hilos de forma concurrente asi como diferentes mecanismos y frameworks de paralelismo y programación de ejecuciones en el tiempo (pools de hilos, Quartz, etc.).
En este primer post mostramos un mecanismo Java estandar muy sencillo para ejecutar una lógica cualquiera dentro de un hilo de ejecución separado y esperar a que acabe, pero tan solo un tiempo máximo, para evitar posibles bloqueos del hilo de ejecución principal.
El planteamiento es el siguiente:
1. Tenemos una lógica de negocio implementada en alguna unidad de ejecución, una clase, un hilo, etc.
1 2 |
/* Mi lógica de negocio solo saca un texto por pantalla */ System.out.println("Hola lógica!!!"); |
2. Podemos ejecutar esa lógica invocando algún método de esa clase o hilo (i.e. el método run()).
1 2 3 4 |
public void run(){ /* Mi lógica de negocio solo saca un texto por pantalla */ System.out.println("Hola lógica!!!"); } |
3. En lugar de ejecutar ese método de forma explicita desde el hilo principal de ejecución de nuestro programa, disponemos de un hilo aparte al que pasaremos esa lógica de negocio y desde el que la ejecutaremos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/** * Executor thread. * * @author luisalbertogh */ class ExecutorThread extends Thread { /** The command agent to execute. */ private Object logic; /** * Constructor * * @param agent - The agent to execute. */ public ExecutorThread(Object logic) { this.logic = logic; } /** * Run the thread. */ @Override public void run() { try { logic.run(); } catch (Exception e) { CRMServerLogger.getLogger(AgentExecutor.class).error("[ExecutorThread] Error executing agent.", e); } } } |
4. Lanzamos el hilo de forma asíncrona (start()) pero en lugar de desentendernos de él, le esperamos un tiempo máximo usando el metodo join() de la API de concurrencia de Java. Ademas, metemos todo dentro de un bloque try-catch de tal manera que, bien ante una excepción o bien cuando finalice la ejecución o se supere el tiempo de espera máximo, se compruebe si el hilo sigue activo (isAlive). Si es así, se solicitará su interrupción para no dejar hilos activos de forma innecesaria (interrupt()).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
ExecutorThread xthread = null; Long milliseconds = 10000; // 10 seconds try { xthread = new ExecutorThread(logic); xthread.start(); xthread.join(milliseconds); } catch (Exception ex) { CRMServerLogger.getLogger(AgentExecutor.class).error( "[InterfacesAgent] Error", ex); } finally { if (xthread != null && xthread.isAlive()) { CRMServerLogger.getLogger(AgentExecutor.class).info( "[InterfacesAgent] Interrupting"); xthread.interrupt(); } } |