martes, 12 de febrero de 2013

Compilación e instalación de servidor Apache en Redhat

Si pretendemos compilar he instalar un Servidor Web Apache (la versión que he instalado es la 2.4) en un sistema tipo Linux (en mi caso un Redhat 4 de 64 bits) recomiendo seguir las indicaciones de la Guía de Compilación e Instalación del Servidor HTTP Apache. Básicamente las indicaciones de la guía son correctas salvo en el apartado Requisitos donde falta indicar que son necesarios para compilar Apache: Apache Portable Runtime Project (APR), Apache Portable Runtime Project Utility y Perl Compatible Regular Expressions (PCRE).





sábado, 2 de febrero de 2013

Trabajando con Threads en Java. Caso 1

Bruce Eckel en su libro Thinking in Java en el capítulo sobre la concurrencia plantea un ejercio que resulta muy ilustrativo sobre sobre como funcionan los Threads en Java.

El enunciado del ejercicio es:


Implement a Runnable. Inside run( ), print a message, and then call yield( ). Repeat this three times, and then return from run( ). Put a startup message in the constructor and a shutdown message when the
task terminates. Create a number of these tasks and drive them using threads

La implementación es simple. En primer lugar definimos una clase Runnable que cumple con los requisitos pedidos.


package thinkinginjava.concurrency.exercise1;

public class RunnablePrinter implements Runnable {

private static int count = 0;

private final int id = count++;

public RunnablePrinter() {
System.out.println("Inicio RunnablePrinter. Id: " + id);
}

public void run() {

Thread t = Thread.currentThread();

System.out.println("#" + id + " Mensaje 1." + " Thread: " + t.getId());
Thread.yield();
System.out.println("#" + id + " Mensaje 2."  + " Thread: " + t.getId());
Thread.yield();
System.out.println("#" + id + " Mensaje 3. " + " Thread: " + t.getId());
Thread.yield();

System.out.println("Fin RunnablePrinter. Id: " + id);

return;
}

}

Y después creamos una clase de tipo main para lanzar los Threads.


package thinkinginjava.concurrency.exercise1;

public class RunnablePrinterMain {

public static void main(String[] args){

for(int i = 0; i < 10; i++)
new Thread(new RunnablePrinter()).start();


}

}


Hasta aquí nada especial. Ahora viene lo interesante, lancemos el main y veamos que sucede.

Una primera ejecución nos devuelve el siguiente resultado:


Inicio RunnablePrinter. Id: 0
Inicio RunnablePrinter. Id: 1
Inicio RunnablePrinter. Id: 2
#1 Mensaje 1. Thread: 8
#1 Mensaje 2. Thread: 8
#1 Mensaje 3.  Thread: 8
Fin RunnablePrinter. Id: 1
Inicio RunnablePrinter. Id: 3
#0 Mensaje 1. Thread: 7
#0 Mensaje 2. Thread: 7
#0 Mensaje 3.  Thread: 7
Fin RunnablePrinter. Id: 0
Inicio RunnablePrinter. Id: 4
#2 Mensaje 1. Thread: 9
#2 Mensaje 2. Thread: 9
#3 Mensaje 1. Thread: 10
#2 Mensaje 3.  Thread: 9
Inicio RunnablePrinter. Id: 5
#3 Mensaje 2. Thread: 10
#3 Mensaje 3.  Thread: 10
Fin RunnablePrinter. Id: 2
Inicio RunnablePrinter. Id: 6
#4 Mensaje 1. Thread: 11
Fin RunnablePrinter. Id: 3
#4 Mensaje 2. Thread: 11
#4 Mensaje 3.  Thread: 11
Fin RunnablePrinter. Id: 4
#5 Mensaje 1. Thread: 12
#5 Mensaje 2. Thread: 12
#5 Mensaje 3.  Thread: 12
Fin RunnablePrinter. Id: 5
Inicio RunnablePrinter. Id: 7
#6 Mensaje 1. Thread: 13
#6 Mensaje 2. Thread: 13
#6 Mensaje 3.  Thread: 13
Fin RunnablePrinter. Id: 6
Inicio RunnablePrinter. Id: 8
#7 Mensaje 1. Thread: 14
#7 Mensaje 2. Thread: 14
#7 Mensaje 3.  Thread: 14
Fin RunnablePrinter. Id: 7
Inicio RunnablePrinter. Id: 9
#8 Mensaje 1. Thread: 15
#8 Mensaje 2. Thread: 15
#8 Mensaje 3.  Thread: 15
Fin RunnablePrinter. Id: 8
#9 Mensaje 1. Thread: 16
#9 Mensaje 2. Thread: 16
#9 Mensaje 3.  Thread: 16
Fin RunnablePrinter. Id: 9

En este resultado se observa como se reparte el tiempo de CPU entre los distintos threads. La ejecución no es secuencial y esto se pone de manfiesto claramente en la primeras líneas del resultado anterior (marcadas en negrita), el thread 8 se ejecuta antes que el thread 8. Al cotrario de cono debería suceder en el caso de una ejecución secuencial.

Una segunda ejecución daría un resultado distinto al anterior.


Inicio RunnablePrinter. Id: 0
Inicio RunnablePrinter. Id: 1
#0 Mensaje 1. Thread: 7
#0 Mensaje 2. Thread: 7
#0 Mensaje 3.  Thread: 7
Fin RunnablePrinter. Id: 0
Inicio RunnablePrinter. Id: 2
#1 Mensaje 1. Thread: 8
#1 Mensaje 2. Thread: 8
#1 Mensaje 3.  Thread: 8
Fin RunnablePrinter. Id: 1
Inicio RunnablePrinter. Id: 3
#2 Mensaje 1. Thread: 9
#2 Mensaje 2. Thread: 9
#2 Mensaje 3.  Thread: 9
Fin RunnablePrinter. Id: 2
Inicio RunnablePrinter. Id: 4
#3 Mensaje 1. Thread: 10
#3 Mensaje 2. Thread: 10
#3 Mensaje 3.  Thread: 10
Fin RunnablePrinter. Id: 3
Inicio RunnablePrinter. Id: 5
#4 Mensaje 1. Thread: 11
#4 Mensaje 2. Thread: 11
#4 Mensaje 3.  Thread: 11
Fin RunnablePrinter. Id: 4
Inicio RunnablePrinter. Id: 6
#5 Mensaje 1. Thread: 12
#5 Mensaje 2. Thread: 12
#5 Mensaje 3.  Thread: 12
Fin RunnablePrinter. Id: 5
Inicio RunnablePrinter. Id: 7
#6 Mensaje 1. Thread: 13
#6 Mensaje 2. Thread: 13
#6 Mensaje 3.  Thread: 13
Fin RunnablePrinter. Id: 6
Inicio RunnablePrinter. Id: 8
#7 Mensaje 1. Thread: 14
#7 Mensaje 2. Thread: 14
#7 Mensaje 3.  Thread: 14
Fin RunnablePrinter. Id: 7
Inicio RunnablePrinter. Id: 9
#8 Mensaje 1. Thread: 15
#8 Mensaje 2. Thread: 15
#8 Mensaje 3.  Thread: 15
Fin RunnablePrinter. Id: 8
#9 Mensaje 1. Thread: 16
#9 Mensaje 2. Thread: 16
#9 Mensaje 3.  Thread: 16
Fin RunnablePrinter. Id: 9

Se observa que no podemos conocer apriori el reparto del tiempo de CPU entre los distintos thread.