Multithreading en Java Tutorial con ejemplos

Cualquier aplicación puede tener múltiples procesos (instancias). Cada uno de estos procesos se puede asignar como un solo hilo o múltiples hilos.

Veremos en este tutorial cómo realizar múltiples tareas al mismo tiempo y también aprender más sobre los hilos y la sincronización entre los hilos.

En este tutorial, aprenderemos-

¿Qué es Single Thread?

Un solo hilo es básicamente un peso ligero y la unidad de procesamiento más pequeña. Java usa subprocesos utilizando una “clase de subprocesos”.

Hay dos tipos de subprocesos: subproceso de usuario e hilo de demonio (los subprocesos de daemon se utilizan cuando queremos limpiar la aplicación y se utilizan en segundo plano).

Cuando una aplicación comienza por primera vez, se crea el hilo de usuario. Publica eso, podemos crear muchos hilos de usuario e hilos daemon.

Ejemplo de un solo hilo:

Ventajas de un solo hilo:

  • Reduce los gastos generales en la aplicación como ejecución de un solo hilo en el sistema
  • Además, reduce el costo de mantenimiento de la aplicación.

¿Qué es Multithreading?

El subprocesamiento múltiple en Java es un proceso de ejecución de dos o más subprocesos simultáneamente para una utilización máxima de la CPU.

Las aplicaciones multiproceso son donde dos o más hilos se ejecutan simultáneamente; por lo tanto, también se conoce como Concurrencia en Java. Esta multitarea está hecha, cuando múltiples procesos comparten recursos comunes como CPU, memoria, etc.

Cada hilo se ejecuta en paralelo el uno al otro. Los subprocesos no asignan área de memoria separada; por lo tanto, ahorra memoria. Además, el cambio de contexto entre hilos lleva menos tiempo.

Ejemplo de hilo múltiple:

Ventajas de multihilo:

  • Los usuarios no están bloqueados porque los hilos son independientes, y podemos realizar varias operaciones a veces
  • Como tal, los hilos son independientes, los otros hilos no se verán afectados si un hilo cumple una excepción.

Thread Life Cycle en Java

El ciclo de vida de un hilo:

Hay varias etapas del ciclo de vida del hilo como se muestra en el diagrama de arriba:

  1. Nuevo
  2. Runnable
  3. Corriendo
  4. Esperando
  5. Muerto
  1. Nuevo:en esta fase, el hilo se crea utilizando la clase “Clase de hilo”. Permanece en este estado hasta que el programa inicia el hilo. También se conoce como hilo nacido.
  2. Runnable:en esta página, la instancia del hilo se invoca con un método de inicio. El control de subproceso se le da al planificador para finalizar la ejecución. Depende del planificador, si ejecutar el hilo.
  3. En ejecución:cuando el subproceso comienza a ejecutarse, el estado cambia al estado “en ejecución”. El programador selecciona un hilo del grupo de subprocesos y comienza a ejecutarse en la aplicación.
  4. Esperando:este es el estado cuando un hilo tiene que esperar. Como hay varios subprocesos ejecutándose en la aplicación, existe una necesidad de sincronización entre los subprocesos. Por lo tanto, un hilo tiene que esperar, hasta que se ejecute el otro hilo. Por lo tanto, este estado se conoce como estado de espera.
  5. Muerto:este es el estado cuando termina el hilo. El subproceso está en estado de ejecución y, tan pronto como finaliza el procesamiento, se encuentra en “estado muerto”.

Algunos de los métodos comúnmente utilizados para los hilos son:

Método Descripción
comienzo() Este método inicia la ejecución del subproceso y JVM llama al método run () en el subproceso.
Sleep (int milisegundos) Este método hace que el subproceso duerma, por lo que la ejecución del subproceso se pausará durante los milisegundos proporcionados y, luego, nuevamente el subproceso comenzará a ejecutarse. Esta ayuda en la sincronización de los hilos.
getName () Devuelve el nombre del hilo.
setPriority (int newpriority) Cambia la prioridad del hilo.
rendimiento () Hace que el hilo actual en alto y otros hilos se ejecuten.

Ejemplo: en este ejemplo vamos a crear un hilo y explorar los métodos incorporados disponibles para los hilos.

Explicación del código:

Línea de código 2: estamos creando una clase “thread_Example1” que implementa la interfaz Runnable (debe implementarla cualquier clase cuyas instancias estén destinadas a ser ejecutadas por el hilo).

Línea de código 4: anula el método de ejecución de la interfaz ejecutable, ya que es obligatorio anular ese método

Línea de código 6: Aquí hemos definido el método principal en el cual comenzaremos la ejecución del hilo.

Línea de código 7: Aquí estamos creando un nuevo nombre de hilo como “guruthread1” al crear una nueva clase de hilo.

Código de la Línea 8: usaremos el método de “inicio” del hilo con la instancia “guruthread1”. Aquí el hilo comenzará a ejecutarse.

Código de la línea 10: aquí estamos utilizando el método “sleep” del hilo con la instancia “guruthread1”. Por lo tanto, el hilo dormirá durante 1000 milisegundos.

Código 9-14: Aquí hemos puesto el método de suspensión en el bloque try catch, ya que hay una excepción marcada que ocurre, es decir, una excepción interrumpida.

Código de línea 15: aquí estamos estableciendo la prioridad del hilo en 1 de la prioridad que fue

Código de la línea 16: aquí estamos obteniendo la prioridad del hilo usando getPriority ()

Línea de código 17: aquí estamos imprimiendo el valor obtenido de getPriority

Línea de código 18: Aquí estamos escribiendo un texto que se está ejecutando.

Cuando ejecuta el código anterior, obtiene el siguiente resultado:

Salida:
5 es la prioridad del subproceso, y el subproceso en ejecución es el texto que es el resultado de nuestro código.

Sincronización de subprocesos de Java

En multihilo, existe el comportamiento asíncrono de los programas. Si un hilo está escribiendo algunos datos y otro hilo que está leyendo datos al mismo tiempo, puede crear inconsistencias en la aplicación.

Cuando hay una necesidad de acceder a los recursos compartidos por dos o más subprocesos, se utiliza el enfoque de sincronización.

Java ha proporcionado métodos sincronizados para implementar un comportamiento sincronizado.

En este enfoque, una vez que el hilo llega al interior del bloque sincronizado, entonces ningún otro hilo puede llamar a ese método en el mismo objeto. Todos los hilos tienen que esperar hasta que el hilo termina el bloque sincronizado y sale de eso.

De esta manera, la sincronización ayuda en una aplicación multiproceso. Un subproceso tiene que esperar hasta que otro subproceso termine su ejecución solo entonces los otros subprocesos se pueden ejecutar.

Puede escribirse de la siguiente forma:

Ejemplo de subprocesamiento múltiple de Java

En este ejemplo, tomaremos dos hilos y buscaremos los nombres del hilo.

Ejemplo 1:

Explicación del código:

Línea de código 3: Hemos tomado una clase “GuruThread1” que implementa Runnable (debe implementarse por cualquier clase cuyas instancias estén destinadas a ser ejecutadas por el hilo).

Código de la línea 8: este es el método principal de la clase

Línea de código 9: Aquí estamos instanciando la clase Thread y creando una instancia llamada “guruThread1” y creando un hilo.

Línea de código 10: Aquí estamos instanciando la clase Thread y creando una instancia llamada “guruThread2” y creando un hilo.

Código de la línea 11: estamos comenzando el hilo, es decir, guruThread1.

Código de la línea 12: estamos comenzando el hilo, es decir guruThread2.

Código de línea 13: la salida del texto como “Los nombres de subprocesos son los siguientes:”

Código de la línea 14: obtener el nombre de la secuencia 1 con el método getName () de la clase de subproceso.

Código de línea 15: Obteniendo el nombre del subproceso 2 utilizando el método getName () de la clase de subproceso.

Cuando ejecuta el código anterior, obtiene el siguiente resultado:

Salida:

Los nombres de los hilos se están imprimiendo aquí como

  • Guru1
  • Guru2

Ejemplo 2:

En este ejemplo, aprenderemos sobre los métodos de anulación run () y start () de una interfaz ejecutable y crearemos dos subprocesos de esa clase y los ejecutaremos en consecuencia.

Además, estamos tomando dos clases,

  • Uno que implementará la interfaz ejecutable y
  • Otro que tendrá el método principal y se ejecutará en consecuencia.

Explicación del código:

Línea de código 2: Aquí estamos tomando una clase “GuruThread2” que tendrá el método principal en ella.

Línea de código 4: Aquí estamos tomando un método principal de la clase.

Línea de código 6-7: Aquí estamos creando una instancia de la clase GuruThread3 (que se crea en las líneas a continuación del código) como “threadguru1” y estamos comenzando el hilo.

Línea de código 8-9: Aquí estamos creando otra instancia de la clase GuruThread3 (que se crea en las líneas a continuación del código) como “threadguru2” y estamos comenzando el hilo.

Línea de código 11: Aquí estamos creando una clase “GuruThread3” que está implementando la interfaz ejecutable (debe implementarse por cualquier clase cuyas instancias estén destinadas a ser ejecutadas por el hilo).

Línea de código 13-14: estamos tomando dos variables de clase de las cuales una es de la clase de subproceso de tipo y otra de la clase de cadena.

Línea de código 15-18: estamos anulando el constructor GuruThread3, que toma un argumento como tipo de cadena (que es el nombre de los hilos) que se asigna a la variable de clase guruname y, por lo tanto, se almacena el nombre del hilo.

Línea de código 20: Aquí estamos anulando el método run () de la interfaz ejecutable.

Línea de código 21: Estamos produciendo el nombre de la secuencia utilizando la instrucción println.

Línea de código 22-31: Aquí estamos usando un bucle for con el contador inicializado a 0, y no debe ser menor que 4 (podemos tomar cualquier número, por lo que aquí el bucle se ejecutará 4 veces) e incrementar el contador. Estamos imprimiendo el nombre del subproceso y también haciendo que el subproceso duerma durante 1000 milisegundos dentro de un bloque try-catch mientras el método sleep aumentó la excepción comprobada.

Línea de código 33: Aquí estamos anulando el método de inicio de la interfaz ejecutable.

Línea de código 35: Estamos generando el texto “Inicio de hilo”.

Código de la línea 36-40: Aquí tomamos una condición if para verificar si la variable de clase guruthread tiene valor en él o no. Si es nulo, entonces estamos creando una instancia utilizando una clase de subproceso que toma el nombre como un parámetro (valor para el cual fue asignado en el constructor). Después de lo cual, el hilo se inicia con el método start ().

Cuando ejecutas el código anterior obtienes la siguiente salida:

Salida :

Hay dos hilos por lo tanto, recibimos dos veces el mensaje “Inicio de hilo”.

Obtenemos los nombres del hilo a medida que los hemos generado.

Entra en el bucle donde estamos imprimiendo el contador y el nombre del hilo y el contador comienza con 0.

El ciclo se ejecuta tres veces y entre el hilo se duerme durante 1000 milisegundos.

Por lo tanto, primero, obtenemos guru1 y luego guru2 y luego guru2 porque el hilo duerme aquí durante 1000 milisegundos y luego el siguiente guru1 y nuevamente guru1, el hilo duerme durante 1000 milisegundos, por lo que obtenemos guru2 y luego guru1.

Resumen :

En este tutorial, vimos aplicaciones multiproceso en Java y cómo usar hilos simples y múltiples.

  • En el multihilo, los usuarios no son bloqueados ya que los hilos son independientes y pueden realizar múltiples operaciones al mismo tiempo
  • Varias etapas del ciclo de vida del hilo son,
    • Nuevo
    • Runnable
    • Corriendo
    • Esperando
    • Muerto
  • También aprendimos sobre la sincronización entre hilos, lo que ayuda a que la aplicación funcione sin problemas.
  • El subprocesamiento múltiple facilita muchas más tareas de aplicación.
0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *