Índice del curso de Java JSE

  1. Introducción
  2. Eclipse
  3. Resolución de problemas
  4. Clases
  5. Objetos
  6. Hola mundo
  7. Comentarios
  8. Variables
  9. Constantes
  10. Operadores
  11. Lectura de datos
  12. Estructuras de control
    1. Estructuras de control: if
    2. Switch
    3. Estructura de control: bucle for
    4. Estructura de control: bucle while
  13. Métodos
  14. Modificador static
  15. Arrays
  16. Ejercicio – juego del ahorcado
  17. Ejercicio - tres en raya
  18. Modificadores de acceso
  19. Constructores
  20. Herencia
  21. Polimorfismo
  22. Sobrecarga y sobreescritura
  23. Abstracción
  24. Interfaces
  25. Clases internas
  26. Garbage Collector
  27. String performance
  28. Encapsulamiento
  29. Contenedores
  30. Genéricos
  31. Ejercicio alta, baja, modificación y consulta en un ArrayList
  32. Ejercicio – juego de la oca
  33. Recorrer un map
  34. Sobreescritura del equals
  35. Sobreescritura del hashcode
  36. Sobreescritura del compareTo
  37. Excepciones
  38. Enumeraciones
  39. Hilos

Hilos

Para usarlos puedo extender thread o implementar Runnable

Dos ejemplos de hilos en la vida real

Cuando se venden las entradas del concierto de Madonna. En poco segundos todas las entradas quedan agotadas debido a la gran demanda. El proceso que materializa la compra de la entrada no debe ser realizado por varios usuarios a la vez, ya que se corre el riesgo de que se vendan más entradas de las que realmente hay disponibles. Esa parte del código habrá que sincronizarla.

Varias personas entran en un supermercado en el que sólo hay un dependiente. Aunque cada cliente deambula por el supermercado a su aire, mirando productos, escogiendo los que tienen menos conservantes, etc. a la hora de pagar los clientes deben ponerse en cola e ir siendo atendidos por el vendedor de uno a uno. Esta sería la parte sincronizada de un algoritmo que representase lo que ocurre en el supermercado.

Ejemplo de aplicación sin usar hilos

Aunque creamos 3 "pseudohilos", realmente no lo son, y el código de un hilo no se ejecutará hasta que no haya concluído el "pseudohilo" anterior.

Main.javapublic class Main {
	public static void main(String args[]){
		HiloFalso hilo1 = new HiloFalso();
		HiloFalso hilo2 = new HiloFalso();
		HiloFalso hilo3 = new HiloFalso();
		hilo1.run();
		hilo2.run();
		hilo3.run();	
	}
}
Hilo.javaclass HiloFalso{
	static double variable1 = 100;
	public void run() {
		variable1-=10;	
		Thread.sleep(500);		
		System.out.println("Variable1:" + variable1);
	}
}

Output:
Variable1:90.0
Variable1:80.0
Variable1:70.0

Extender Thread

Cuando en una instancia que herede de thread llamo al método start estoy invocando el método run de la clase en un nuevo hilo.

Si llamase el método run directamente, estaría ejecutando su código pero sin crear un nuevo hilo.

Método Main para las siguientes implementaciones de hilos:public static void main(String args[]){
	Hilo hilo1 = new Hilo();
	Hilo hilo2 = new Hilo();
	Hilo hilo3 = new Hilo();
		
	hilo1.start();
	hilo2.start();
	hilo3.start();
		
}

Puedo asignar prioridad a los hilos usando:
Hilo1.setPriority((Thread.MAX_PRIORITY - Thread.NORM_PRIORITY) / 2);

Sin sincronización

class Hilo extends Thread{
	static double variable1 = 100;
	public void run() {
		try {
			variable1-=10;
			Thread.sleep(500);
			System.out.println("Variable1:" + variable1 );
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

Ponemos los hilos a dormir para asegurarnos de que en algún momento todos los hilos están ejecutando simultáneamente el método run().

Output:
Variable1:70.0
Variable1:70.0
Variable1:70.0

Modificador synchronized

Sólo permite que un hilo pase por cierto código de cada vez.

Cuando un objeto está sincronizado, se dice que dicho objeto es un monitor y tiene una variable lock.

El lock tiene el id de un hilo.

Con sincronización

class Hilo extends Thread{
	static Object mutex = new Object();
	static double variable = 100;
	public void run() {
		//El parámetro del siguiente método es un objeto (un Object, un String, un Integer...) no nulo sobre el cual se va a sincronizar.EL objeto mutex sería una especie de guardia de tráfico que decide quien pasa y quien no
		synchronized(mutex){ 
			try {
				Variable-=10;			//90 80 70
				Thread.sleep(500);
				System.out.println("Variable1:" + variable);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

Output:
Variable1:90.0
Variable1:80.0
Variable1:70.0

Implementar Runnable

Me creo una instancia de la clase Thread, pasándole como parámetro un objeto de una clase que implementa la interfaz Runnable.

Método Main de las siguientes implementaciones de hilos:
public class Main {

	public static void main(String args[]){
		Thread hilo1 = new Thread(new Hilo());
		Thread hilo2 = new Thread(new Hilo());
		Thread hilo3 = new Thread(new Hilo());
		
		hilo1.start();
		hilo2.start();
		hilo3.start();		
	}
}

Nota:
¿Por qué existe la interfaz Runnable?
Porque en Java sólo es posible heredar de una clase y por tanto a veces no será posible hereder de la clase Thread.

Sin sincronización

		
class Hilo implements Runnable{
	static double variable = 100;
	public void run() {
		try {
			variable-=10;			//70 70 70
			Thread.sleep(500);
			System.out.println("Variable1:" + variable);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

Output:
Variable1:70.0
Variable1:70.0
Variable1:70.0

Con sincronización

class Hilo implements Runnable{
	
	static Object mutex = new Object();
	static double variable = 100;
	public void run() {
		synchronized(mutex){ //Aquí viene un objeto (un Object, un String, un Integer...) no nulo 	sobre el cual se va a sincronizar. Es posible usar cualquier objeto porque los métodos que hacen de semáforo pertenecen a la clase Object.
		//EL objeto mutex sería una especie de guardia de tráfico que decide quien pasa y quien no
			try {
				variable-=10;		//90 80	70
				Thread.sleep(500);
				System.out.println("Variable1:" + variable);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

Output:
Variable1:90.0
Variable1:80.0
Variable1:70.0

icono de mandar un mail¡Contacta conmigo!
Pablo Monteserín
contacta conmigoPablo Monteserín

Para dudas técnicas sobre los ejercicios de mis cursos es necesario estar suscrito.