Multitarea e Hilos en Java con ejemplos (Thread & Runnable)


El proyecto de este post lo puedes descargar pulsando AQUI.

En esta entrada vamos a ver las diferentes maneras de como trabajar con Threads en Java (o hilos en español). Sino tienes muy claro el concepto de la multitarea te recomendamos que te leas primero la entrada de Multitaréa e Hilos, fácil y muchas ventajas aunque en esta entrada también veremos (en menor detalle) los conceptos y las ventajas de la multitarea.

En esencia la multitarea nos permite ejecutar varios procesos a la vez; es decir, de forma concurrente y por tanto eso nos permite hacer programas que se ejecuten en menor tiempo y sean más eficientes. Evidentemente no podemos ejecutar infinitos procesos de forma concurrente ya que el hardware tiene sus limitaciones, pero raro es a día de hoy los ordenadores que no tengan más de un núcleo por tanto en un procesador con dos núcleos se podrían ejecutar dos procesos a la vez y así nuestro programa utilizaría al máximo los recursos hardware. Para que veáis la diferencia en un par de imágenes, supongamos que tenemos un programa secuencial en el que se han de ejecutar 4 procesos; uno detrás de otro, y estos tardan unos segundos:

Threads_Un_unico_hilo

Si en vez de hacerlo de forma secuencial, lo hiciésemos con 4 hilos, el programa tardaría en ejecutarse solo 20 segundos, es decir el tiempo que tardaría en ejecutarse el proceso más largo. Esto evidentemente sería lo ideal, pero la realidad es que no todo se puede paralelizar y hay que saber el número de procesos en paralelo que podemos lanzar de forma eficiente. En principio en esta entrada no vamos a hablar sobre ello ya que el objetivo de la misma es ver como se utilizan los hilos en java con un ejemplo relativamente sencillo y didáctico.

Threads_Varios_hilos

En Java para utilizar la multitarea debemos de usar la clase Thread (es decir que la clase que implementemos debe heredar de la clase Thread) y la clase Thread implementa la Interface Runnable. En el siguiente diagrama de clase mostramos la Interface Runnable y la clase Thread con sus principales métodos:

MultiHilos_Jarroba_Diagrama_de_clases

En esta entrada no vamos a ver como utilizar todos los métodos de la clase Thread, pero os los mostramos para que sepáis que existen y a parte por su nombre podéis intuir su funcionalidad.

En esta entrada vamos a poner un ejemplo para que veáis las ventajas de la multitarea, viendo como se ejecutaría un programa sin utilizar la multitarea y otro utilizándola.

En este ejemplo vamos a simular el proceso de cobro de un supermercado; es decir, unos clientes van con un carro lleno de productos y una cajera les cobra los productos, pasándolos uno a uno por el escaner de la caja registradora. En este caso la cajera debe de procesar la compra cliente a cliente, es decir que primero le cobra al cliente 1, luego al cliente 2 y así sucesivamente. Para ello vamos a definir una clase "Cajera" y una clase "Cliente" el cual tendrá un "array de enteros" que representaran los productos que ha comprado y el tiempo que la cajera tardará en pasar el producto por el escaner; es decir, que si tenemos un array con [1,3,5] significará que el cliente ha comprado 3 productos y que la cajera tardara en procesar el producto 1 '1 segundo', el producto 2 '3 segundos' y el producto 3 en '5 segundos', con lo cual tardara en cobrar al cliente toda su compra '9 segundos'.

Explicado este ejemplo vamos a ver como hemos definido estas clases:

Clase "Cajera.java":

public class Cajera {

	private String nombre;

	// Constructor, getter y setter

	public void procesarCompra(Cliente cliente, long timeStamp) {

		System.out.println("La cajera " + this.nombre + 
				" COMIENZA A PROCESAR LA COMPRA DEL CLIENTE " + cliente.getNombre() + 
				" EN EL TIEMPO: " + (System.currentTimeMillis() - timeStamp) / 1000	+
				"seg");

		for (int i = 0; i < cliente.getCarroCompra().length; i++) { 
				this.esperarXsegundos(cliente.getCarroCompra()[i]); 
				System.out.println("Procesado el producto " + (i + 1) +  
				" ->Tiempo: " + (System.currentTimeMillis() - timeStamp) / 1000 + 
				"seg");
		}

		System.out.println("La cajera " + this.nombre + " HA TERMINADO DE PROCESAR " + 
				cliente.getNombre() + " EN EL TIEMPO: " + 
				(System.currentTimeMillis() - timeStamp) / 1000 + "seg");

	}


	private void esperarXsegundos(int segundos) {
		try {
			Thread.sleep(segundos * 1000);
		} catch (InterruptedException ex) {
			Thread.currentThread().interrupt();
		}
	}

}

Clase "Cliente.java":

public class Cliente {

	private String nombre;
	private int[] carroCompra;

	// Constructor, getter y setter

}

Si ejecutásemos este programa propuesto con dos Clientes y con un solo proceso (que es lo que se suele hacer normalmente), se procesaría primero la compra del Cliente 1 y después la del Cliente 2, con lo cual se tardará el tiempo del Cliente 1 + Cliente 2. A continuación vamos a ver como programamos el método Main para lanzar el programa. CUIDADO: Aunque hayamos puesto dos objetos de la clase Cajera (cajera1 y cajera2) no significa que tengamos dos cajeras independientes, lo que estamos diciendo es que dentro del mismo hilo se ejecute primero los métodos de la cajera1 y después los métodos de la cajera2, por tanto a nivel de procesamiento es como si tuviésemos una sola cajera:

Clase "Main.java":

public class Main {

	public static void main(String[] args) {

		Cliente cliente1 = new Cliente("Cliente 1", new int[] { 2, 2, 1, 5, 2, 3 });
		Cliente cliente2 = new Cliente("Cliente 2", new int[] { 1, 3, 5, 1, 1 });

		Cajera cajera1 = new Cajera("Cajera 1");
		Cajera cajera2 = new Cajera("Cajera 2");

		// Tiempo inicial de referencia
		long initialTime = System.currentTimeMillis();

		cajera1.procesarCompra(cliente1, initialTime);
		cajera2.procesarCompra(cliente2, initialTime);
	}
}

Si ejecutamos este código tendremos lo siguiente:

La cajera Cajera 1 COMIENZA A PROCESAR LA COMPRA DEL CLIENTE Cliente 1 EN EL TIEMPO: 0seg
Procesado el producto 1 ->Tiempo: 2seg
Procesado el producto 2 ->Tiempo: 4seg
Procesado el producto 3 ->Tiempo: 5seg
Procesado el producto 4 ->Tiempo: 10seg
Procesado el producto 5 ->Tiempo: 12seg
Procesado el producto 6 ->Tiempo: 15seg
La cajera Cajera 1 HA TERMINADO DE PROCESAR Cliente 1 EN EL TIEMPO: 15seg
La cajera Cajera 2 COMIENZA A PROCESAR LA COMPRA DEL CLIENTE Cliente 2 EN EL TIEMPO: 15seg
Procesado el producto 1 ->Tiempo: 16seg
Procesado el producto 2 ->Tiempo: 19seg
Procesado el producto 3 ->Tiempo: 24seg
Procesado el producto 4 ->Tiempo: 25seg
Procesado el producto 5 ->Tiempo: 26seg
La cajera Cajera 2 HA TERMINADO DE PROCESAR Cliente 2 EN EL TIEMPO: 26seg

Como vemos se procesa primero la compra del cliente 1 y después la compra del cliente 2 tardando en procesar ambas compras un tiempo de 26 segundos.

Compra_1_cajera_1_hilo

¿Y si en vez de procesar primero un cliente y después otro, procesásemos los dos a la vez?, ¿Cuanto tardaría el programa en ejecutarse?. Pues bien si en vez de haber solo una Cajera (es decir un solo hilo), hubiese dos Cajeras (es decir dos hilos o threads) podríamos procesar los dos clientes a la vez y tardar menos tiempo en ejecutarse el programa. Para ello debemos de modificar la clase "Cajera.java" y hacer que esta clase herede de la clase Thread para heredar y sobre-escribir algunos de sus métodos. Primero vamos a ver como codificamos esta nueva clase "CajeraThread.java" y después explicamos sus caracteristicas.

public class CajeraThread extends Thread {

	private String nombre;

	private Cliente cliente;

	private long initialTime;

	// Constructor, getter & setter

	@Override
	public void run() {

		System.out.println("La cajera " + this.nombre + " COMIENZA A PROCESAR LA COMPRA DEL CLIENTE " 
					+ this.cliente.getNombre() + " EN EL TIEMPO: " 
					+ (System.currentTimeMillis() - this.initialTime) / 1000 
					+ "seg");

		for (int i = 0; i < this.cliente.getCarroCompra().length; i++) { 
			this.esperarXsegundos(cliente.getCarroCompra()[i]); 
			System.out.println("Procesado el producto " + (i + 1) 
			+ " del cliente " + this.cliente.getNombre() + "->Tiempo: " 
			+ (System.currentTimeMillis() - this.initialTime) / 1000 
			+ "seg");
		}

		System.out.println("La cajera " + this.nombre + " HA TERMINADO DE PROCESAR " 
						+ this.cliente.getNombre() + " EN EL TIEMPO: " 
						+ (System.currentTimeMillis() - this.initialTime) / 1000 
						+ "seg");
	}

	private void esperarXsegundos(int segundos) {
		try {
			Thread.sleep(segundos * 1000);
		} catch (InterruptedException ex) {
			Thread.currentThread().interrupt();
		}
	}

}

Lo primero que vemos y que ya hemos comentado es que la clase "CajeraThread" debe de heredar de la clase Thread: "extendsThread".

Otra cosa importante que vemos es que hemos sobre-escrito el método  "run()" (de ahi la etiqueta @Override) . Este método es imprescindibles sobre-escribirlo (ya que es un método que esta en la clase Runnable y la clase Thread Implementa esa Interface) porque en él se va a codificar la funcionalidad que se ha de ejecutar en un hilo; es decir, que lo que se programe en el método "run()" se va a ejecutar de forma secuencial en un hilo. En esta clase "CajeraThread" se pueden sobre-escribir más métodos para que hagan acciones sobre el hilo o thread como por ejemplo, parar el thread, ponerlo en reposos, etc. A continuación vamos a ver como programamos el método Main para que procese a los clientes de forma paralela y ver como se tarda menos en procesar todo. El método Main esta en la clase "MainThread.java" que tiene el siguiente contenido:

public class MainThread {

	public static void main(String[] args) {

		Cliente cliente1 = new Cliente("Cliente 1", new int[] { 2, 2, 1, 5, 2, 3 });
		Cliente cliente2 = new Cliente("Cliente 2", new int[] { 1, 3, 5, 1, 1 });

		// Tiempo inicial de referencia
		long initialTime = System.currentTimeMillis();
		CajeraThread cajera1 = new CajeraThread("Cajera 1", cliente1, initialTime);
		CajeraThread cajera2 = new CajeraThread("Cajera 2", cliente2, initialTime);

		cajera1.start();
		cajera2.start();
	}
} 

Ahora vamos a ver cual sería el resultado de esta ejecución y vamos a comprobar como efectivamente el programa se ejecuta de forma paralela y tarda solo 15 segundos en terminar su ejecución:

La cajera Cajera 1 COMIENZA A PROCESAR LA COMPRA DEL CLIENTE Cliente 1 EN EL TIEMPO: 0seg
La cajera Cajera 2 COMIENZA A PROCESAR LA COMPRA DEL CLIENTE Cliente 2 EN EL TIEMPO: 0seg
Procesado el producto 1 del cliente Cliente 2->Tiempo: 1seg
Procesado el producto 1 del cliente Cliente 1->Tiempo: 2seg
Procesado el producto 2 del cliente Cliente 2->Tiempo: 4seg
Procesado el producto 2 del cliente Cliente 1->Tiempo: 4seg
Procesado el producto 3 del cliente Cliente 1->Tiempo: 5seg
Procesado el producto 3 del cliente Cliente 2->Tiempo: 9seg
Procesado el producto 4 del cliente Cliente 2->Tiempo: 10seg
Procesado el producto 4 del cliente Cliente 1->Tiempo: 10seg
Procesado el producto 5 del cliente Cliente 2->Tiempo: 11seg
La cajera Cajera 2 HA TERMINADO DE PROCESAR Cliente 2 EN EL TIEMPO: 11seg
Procesado el producto 5 del cliente Cliente 1->Tiempo: 12seg
Procesado el producto 6 del cliente Cliente 1->Tiempo: 15seg
La cajera Cajera 1 HA TERMINADO DE PROCESAR Cliente 1 EN EL TIEMPO: 15seg

En este ejemplo vemos como el efecto es como si dos cajeras procesasen la compra de los clientes de forma paralela sin que el resultado de la aplicación sufra ninguna variación en su resultado final, que es el de procesar todas las compras de los clientes de forma independiente. De forma gráfica vemos que el programa ha realizado lo siguiente en dos hilos distintos:

Compra_2_hilos

Otra forma de hacer lo mismo pero sin heredar de la clase "Thread" es implementar la Interface "Runnable". En este caso no dispondremos ni podremos sobre-escribir los métodos de la clase Thread ya que no la vamos a utilizar y solo vamos a tener que sobre-escribir el método "run()". En este caso solo será necesario implementar el método "run()" para que los procesos implementados en ese método se ejecuten en un hilo diferente. Vamos a ver un ejemplo de como utilizando objetos de las clases "Cliente.java" y "Cajera.java" podemos implementar la multitarea en la misma clase donde se llama al método Main de la aplicación. A continuación vemos la codificación en la clase "MainRunnable.java":

public class MainRunnable implements Runnable{
	
	private Cliente cliente;
	private Cajera cajera;
	private long initialTime;
	
	public MainRunnable (Cliente cliente, Cajera cajera, long initialTime){
		this.cajera = cajera;
		this.cliente = cliente;
		this.initialTime = initialTime;
	}

	public static void main(String[] args) {
		
		Cliente cliente1 = new Cliente("Cliente 1", new int[] { 2, 2, 1, 5, 2, 3 });
		Cliente cliente2 = new Cliente("Cliente 2", new int[] { 1, 3, 5, 1, 1 });
		
		Cajera cajera1 = new Cajera("Cajera 1");
		Cajera cajera2 = new Cajera("Cajera 2");
		
		// Tiempo inicial de referencia
		long initialTime = System.currentTimeMillis();
		
		Runnable proceso1 = new MainRunnable(cliente1, cajera1, initialTime);
		Runnable proceso2 = new MainRunnable(cliente2, cajera2, initialTime);
		
		new Thread(proceso1).start();
		new Thread(proceso2).start();

	}

	@Override
	public void run() {
		this.cajera.procesarCompra(this.cliente, this.initialTime);
	}

}

En este caso implementamos el método "run()" dentro de la misma clase donde se encuentra el método Main, y en el llamamos al método de "procesarCompra()" de la clase Cajera. Dentro del método Main, nos creamos dos objetos de la misma clase en la que estamos ("new MainRunnable") y nos creamos dos objetos de la clase Thread para lanzar los proceso y que se ejecuten estos en paralelo. El resultado de esta ejecución es el mismo que en el caso anterior:

La cajera Cajera 2 COMIENZA A PROCESAR LA COMPRA DEL CLIENTE Cliente 2 EN EL TIEMPO: 0seg
La cajera Cajera 1 COMIENZA A PROCESAR LA COMPRA DEL CLIENTE Cliente 1 EN EL TIEMPO: 0seg
Procesado el producto 1 del cliente Cliente 2->Tiempo: 1seg
Procesado el producto 1 del cliente Cliente 1->Tiempo: 2seg
Procesado el producto 2 del cliente Cliente 2->Tiempo: 4seg
Procesado el producto 2 del cliente Cliente 1->Tiempo: 4seg
Procesado el producto 3 del cliente Cliente 1->Tiempo: 5seg
Procesado el producto 3 del cliente Cliente 2->Tiempo: 9seg
Procesado el producto 4 del cliente Cliente 2->Tiempo: 10seg
Procesado el producto 4 del cliente Cliente 1->Tiempo: 10seg
Procesado el producto 5 del cliente Cliente 2->Tiempo: 11seg
La cajera Cajera 2 HA TERMINADO DE PROCESAR Cliente 2 EN EL TIEMPO: 11seg
Procesado el producto 5 del cliente Cliente 1->Tiempo: 12seg
Procesado el producto 6 del cliente Cliente 1->Tiempo: 15seg
La cajera Cajera 1 HA TERMINADO DE PROCESAR Cliente 1 EN EL TIEMPO: 15seg

CONCLUSIONES Y ACLARACIONES:

El concepto de multitarea o multiprocesamiento es bastante sencillo de entender ya que solo consiste en hacer varias cosas a la vez sin que se vea alterado el resultado final. Como ya se ha dicho en la entrada no todo se puede paralelizar y en muchas ocasiones suele ser complicado encontrar la manera de paralelizar procesos dentro de una aplicación sin que esta afecte al resultado de la misma, por tanto aunque el concepto sea fácil de entender el aplicarlo a un caso práctico puede ser complicado para que el resultado de la aplicación no se vea afectado.

Por otro lado para los que empecéis a ver estos temas de la concurrencia, multitarea y demás, no so preocupéis al principio si os cuesta programar problemas de este tipo ya que a parte de la multitarea se mezclan cosas como la herencia y las Interfaces que al principio son cosas que cuestan de asimilar, así que ir poco a poco pero tener muy claro que la multitarea es muy util y se ha de aplicar para hacer las aplicaciones más eficientes y que den mejor rendimiento.

Comparte esta entrada en:
Safe Creative #1401310112503
Multitarea e Hilos en Java con ejemplos (Thread & Runnable) por "www.jarroba.com" esta bajo una licencia Creative Commons
Reconocimiento-NoComercial-CompartirIgual 3.0 Unported License.
Creado a partir de la obra en www.jarroba.com

58 comentarios en “Multitarea e Hilos en Java con ejemplos (Thread & Runnable)”

  1. Una duda, quiero utulizar 2 hilos, un hilo tiempo y un hilo de escritura infinito, lo que quiero hacer es que cuando el hilo tiempo finalice, que el hilo de escritura también finalice. ¿Qué me recomiendas utilizar en ese caso?

  2. Hola Buenos días, me estoy iniciando recién con los temas de hilos y me a surgido una duda. Al ocupar el metodo join() para que finalice un hilo antes de comenzar el otro hilo, con este metodo, el funcionamiento de hilos ya no aplicaria.?? ya que la idea no es que se ejecuten paralelo.?? Muchas gracias.

    1. Cuando llamas a strart() se inicia un segundo hilo, pero le hilo principal continua. El hilo principal continua hasta que llega al join(), donde espera a que termine el hilo segundo. Por lo que sí aplica el funcionamiento de hilos (al menos siempre está el hilo principal, más lo que inicies con start() ) aunque luego venga otro hilo 😉

  3. disculpa si mi clase cajera yo la voy a manejar con Cola y tengo 3 cajeras y quiero q la tres cajeras realicen su proceso al mismo tiempo bueno cada vez que tengan un cliente. se puede realizar con hilos??

    1. Entiendo que vas a utilizar la clase Queue (o la estructura de datos que necesites: List, Array, etc) y que vas a tener ahí los tres Threads. Si vas desapilando cada uno e iniciándo (start) cada hilo, te debería de funcionar como necesitas.

  4. Tengo una duda.. si quiero correr varios hilos para realizar una tarea, un for por ejemplo, pero la siguiente tarea debe esperar que todos esos hilos terminen, como se realiza?

    1. Puedes utilizar el método join() para esperar a que terminen los hilos y continuar desde ese punto:

      Thread t1 = new Thread();

      Thread t2 = new Thread();

      Thread t3 = new Thread();

      Thread t4 = new Thread();

      t1.start();

      t2.start();

      t3.start();

      t4.start();

      // Para esperar en este hilo a que acaben los anteriores hilos iniciados, utilizamos join()

      t1.join();

      t2.join();

      t3.join();

      t4.join();

  5. Buen tutorial, pero mi duda es que dejaste el @override en run cuando implementas Runnable y el eclipse marcca erróneo.

    saludos

    1. La anotación @override marca sobrescritura, es más para facilitar la lectura del programador, para que se sepa que se está sobrescribiendo. No es obligatorio, por lo que si la configuración de Eclipse te da error puedes quitarlo. De cualqueir manera, es un poco extraño que te de error las anotaciones, puede que estés trabajando con una versión antigua de Java.

  6. Hola instructores. Tengo un  ejemplo de JLabel con una pelota que rebota en los bordes con diferentes ángulos. y mi labor es hacer que por cada CLICK que yo haga dentro del JLabel me aparezca una nueva pelota.

    Como hago eso, yo soy nuevo en esto y es mi primer laboratorio de este semeste.

    Aqui les copio lo que me estan pidiendo.

    Modify the program so that the Sprite class implements the Runnable interface and the sprite moves itself (25 times per second, which is the original frame rate) with its own thread of execution (the invocation of the sprite's move method will no longer belong in the main animation loop of the SpritePanel). 3. Modify the program so that each additional mouse click adds an additional bouncing sprite rather than replacing the previous sprite. 4. Run the jvisualvm program included with the JDK to confirm that each sprite on the screen has its own thread of execution. (Your Professor has demonstrated how to use this program in the Lecture and/or Lab class.)

    1. No te puedo dar la solucción completa, pues sería contraproducente para tus estudios e iría en contra de nuestros principios de enseñar (y de la misión de tu profesor para que aprendas); pero te puedo dar unas pistas: Si la pelota se mueve sin tener que bloquearse y el usuario tiene que hacer click sin tener que bloquearse, puede que lo más apropiado sean unos hilos. El resto ya es practicar 😉

  7. Hola. Excelente Tutorial. Hago Una consulta. Estoy tratando de dibujar en un JLabel varias pelotitas que rebotan en los bordes con diferentes ángulos. Trato que cada pelota sea un hilo (thread) y que tenga conciencia de los limites y angulos para rebotar. Tengo un problema que con dibujar y redibujar su posicion contantemente, como deberia manejar el repaint? tengo entendido que tambien es un hilo el que pinta y repinta? los componentes.

  8. Te hago una consulta, una vez que sabes cual es el hilo que esta corriendo (runnable) hay forma de saber que clase es la que se esta ejecutando y a su vez que metodo de esa clase?

  9. Tengo una pregunta, cómo se implementaría si en vez de ser dos clientes fueran n clientes? es decir, hay dos cajeras pero para un número indeterminado de clientes y si quieres rizar más el rizo, que se sitúan de forma aleatoria en una cajera u otra…

    Muchas gracias.

  10. Muy buen tutorial sobre el tema. solo me queda una duda que no he conseguido ver como hacer y es como mediante Runnnable arancar dos procesos diferentes, en vez de dos copias del mismo (cajera). si lo he conseguido mediante threads y con esto me ha valido. La pregunta es unicamente por curiosidad y formacion.

     

     

  11. Richard, tengo una duda, a ver si me puedes ayudar. Tengo que lanzar unos modelos de simulación numérica cuyo proceso lleva bastante tiempo. El programa tiene implementada la opción de paralelización, y tengo en el PC un dispositivo que permite proceso GPU. Tengo que optimizar el tiempo al máximo, así que quiero ejecutar varios procesos a la vez. En el PC tengo 4 cores, así que entiendo que no debo definir más de 4 threads, pero mi duda es la siguiente: ¿cómo puede ser más eficaz la ejecución de los procesos simultáneos? No tengo claro cómo funciona lo del GPU y la paralelización, porque hasta ahora manejaba otro PC, en el que una vez lanzado el proceso accedía al administrador de tareas y modificaba ahí la afinidad de cada no en función de los núcleos. Mi duda es si debo ejecutar 4 procesos de forma simultánea activando en todos ellos el GPU y estableciendo un único thread en cada uno, o si es mas eficaz ejecutarlos estableciendo más de un thread. Si ejecuto los 4 procesos de cálculo a la vez y defino 4 threads en cada uno, ¿estoy mejorando la eficacia o de esa forma no paralelizo nada? ¿Para mejorar la eficacia es necesario que establezca un solo thread para cada proceso?

    He hecho una prueba y si ejecuto dos simulaciones a la vez estableciendo 4 threads en cada una de ellas, tarda justo la mitad que si ejecuto 4 simulaciones a la vez con 4 threads en cada una (en todos los casos activando el GPU), por lo que me parece que no estoy paralelizando nada…

    Gracias

  12. Gracias por el aporte, he tomado de lo que has publicado para mi proyecto, ufff fue díficil porque es una mezcla entre clase que implementa Runnable y un actualidador de lista de canales RSS.

  13. Que buen artículo, se agradece siempre el compartir los conocimientos 🙂

    Tengo una duda que quisiera ver si me puedes explicar, soy novato en Java…

    Si tuviera un archivo de tipo txt que quisiera leer X cantidad de veces de forma paralela (por ejemplo 5 hilos, leer de forma paralela 5 veces el archivo)… ¿Cómo tendría que ser la rutina para esto?…

    Gracias de antemano!

    1. No he probado a abrir varias veces el mismo fichero con varios hilos, pero seguramente cuando lo abras con un hilo lo bloquearás y no te permitirá abrirlo con más. Simplemente obtén el contenido del fichero en una variable y multiplícalo en cada hilo que quieras realizar la lectura.

  14. hola,

    si quisiera que  un proceso  corra durante unos minutos, (suponiendo que se generan ls clientes  aleatoriamente) como hago para dejarlo corriendo en un ciclo mientras con la condicion de que no hallan pasado los dos minutos?? se puede hacer eso???

    1. Hola Irene. Puedes hacer lo fácil (aunque a mí no me gusta mucho y no te asegura que justo a los 2 minutos se termine) que es “System.currentTimeMillis()” para capturar el tiempo actual en milisegundos, y sumarle dos minutos para obtener el momento de parada, solo te quedaría ir preguntando a cada iteración si se ha sobrepasado el tiempo. Otra es utilizar las clases Timer de Java, tienes ejemplos en https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html

    1. Hola Adolfo.

      Ya tienes el proyecto compartido en Git, que por algún motivo debimos borrar el repositorio sin querrer. Gracias por avisarnos.

      SL2

    1. Hola Jorge.

      Simplemente te debes de ir a la carpeta donde tengas es fichero java (NombreFichero.java) y poner lo siguiente: "java NombreFichero.java" y ya se ejecutará tu programa, eso siempre y cuando tengas instalada la maquina virtual java.

      SL2

  15. Hola,
    El link para descargar el proyecto al principio de esta pagina no funciona, podrían arreglarlo. Muchas gracias por todo el contenido de la pagina.

  16. !Hola! Esta muy completo lo que han explicado sobre los hilos, sin embargo tengo una duda se puede implementar creando una interfaz y como que herramientas puedo utilizar de ser así?

  17. Muy buena la explicacion de hilos. Aunque tengo una duda. Utilizando Thread si el numero de personas es mayor que el número de cajeras como lo resolvemos?

    Gracias!!

    1. Hola Jose Antonio.
      Muy buena pregunta la que planteas. Para hacer eso requiere un poco mas de control sobre los threads y aunque no es muy complejo, requiere una explicación bastante detallada como para explicarlo en un comentario. En breve publicaremos un tutorial de como hacer eso que planteas ya que estamos viendo que las entradas que hacemos sobre multiproceso están teniendo bastante exito. Gracias por tu comentario y por motivarnos ha hacer un tutorial más sobre el tema que planteas. En breve te daremos la solución en una nueva entrada.
      SL2

  18. Los felicito, ejemplo completo y entendible con código acorde a la POO, tomare este y algunos otros artículos como referencias para las clases que dicto.

  19. Saludos! Esta muy bien explicado el tema, sigan asi, muchas gracias. Me podrias decir que IDE utilizaste? esque me gustó porque esta muy legible el código, gracias!

  20. Hola gracias por la informacion, sin embargo lo que estoy buscando es el consumo de un web service por medio de multithread, me explico tengo un web service con cuatro operaciones basicas suma, resta, multiplicacion y division. la idea es que apartir de una aplicacion de escritorio se consuma el web service haciendo uso de los hilos podrias ayudarme con ello?

    yo lo he intentado de varias maneras pero siempre me ocurre que cuando llamo el metodo .start me sale un error que dice que es indefinido

    este es el codigo de invocacion

    package WebServiceMatematicas.hilos;
    import WebServiceMatematicas.ImplOpMatematicas;
    import WebServiceMatematicas.ImplOpMatematicasProxy;
    public class Proceso {
    public static void main(String[] args) {
    ImplOpMatematicas hilo1 = new ImplOpMatematicasProxy(“http://localhost:8080/WebServicedistri/services/ImplOpMatematicas”);
    hilo1.start(); //Es aca donde me aparece el error
    }
    }

    de antemano muchas gracias

  21. Gran artículo!! Es un placer leer estos temas sobre java porque ayudáis a muchas personas. Tenéis mucho mérito con todo lo que hacéis. Esta web es buenísima. Enhorabuena!

    1. Una pregunta, ¿Que diferencia hay entre crear hilos a través de la herencia de la clase Thread y crearlos a través de la implementación de la interfaz Runnable? ¿Alguna forma es la más usada por los programadores? ¿Existe alguna ventaja?

  22. Saludos.

    Soy nuevo en el área de la programación java. Y queria saber acerca de un ejemplo sencillo de como puedo manejar esto en programacion objeto. Por ejemplo como un semaforo.

  23. Hola, me parece interesante tu tutorial y la forma como explicas sobre multitarea, pero tengo una consulta, lo que haz mostrado es referente a la misma función cajera, osea hacer dos tareas simultáneas usando la misma función cajera, pero como se haría si fueran dos funciones distintas?
    Por ejemplo quiero enviar y recibir datos por socket, mi cliente en android y mi servidor en java, por el lado de mi servidor quiero que haga una multitarea, por un lado recibiendo el dato del cliente y por el otro lado en todo momento leer si ingreso un dato por teclado y enviarlo al cliente. El problema es que no se como hacer que me lea el teclado en todo momento. Tengo en un while(true) la ejecución de recepción de datos del cliente, pero imagino que tendría que usar multitarea para que me lea en todo momento el teclado y enviarlo al cliente.
    Agradecería tus comentarios!!!
    Nícolas

    1. Hola Nícolas,

      se haría de manera similar pero con dos clases diferentes. Aquí la complicación radicaría en la comunicación entre las clases que extienden de Thread, para no saltarte la seguridad de hilos (por ejemplo, evitando el interbloqueo).
      De cualquier manera, para Android no necesitas preocuparte por los hilos, ya que los eventos te solucionan esta parte. Para leer los cambios (introducción por teclado) de un EditText puedes utilizar:
      EditText et = (EditText) findViewById(R.id.miViewEditText);

      et.addTextChangedListener(new TextWatcher() {
      public void afterTextChanged(Editable s) {
      // Hacer algo después de cambiar el texto
      }

      public void beforeTextChanged(CharSequence s, int start, int count, int after) {
      // Hacer algo antes de cambiar el texto
      }

      public void onTextChanged(CharSequence s, int start, int before, int count) {
      // Hacer algo al momento de cambiar el texto
      }
      });
      }

  24. Hola amigos, excelente tutorial la verdad.
    Podrian hacer un tutorial acerca de la sincronizacion de Hilos?
    He estado buscando un poco, pero no encuentro nada asi de bien explicado como lo hacen ustedes.
    Muchas gracias!

    1. Hola Andrés,

      tenemos muchos proyectos entre los que se encuentran más tutoriales sobre hilos. Apuntamos tu sugerencia y la daremos prioridad; avisar que no lo publicaremos pronto, nos gusta hacer los artículos lo más perfectos y fáciles de comprender posible eso requiere tiempo 😉

      1. Genial, a mi me gusta mucho Java y siempre ando aprendiendo algo nuevo.
        Como les dije antes su pagina es muy ilustrativa y ayuda mucho a entender de mejor forma este lenguaje.
        Gracias!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies

ACEPTAR
Aviso de cookies