Tutorial de subprocesos múltiples en Java con ejemplos

Cualquier aplicación puede tener múltiples procesos (instancias). Cada uno de estos procesos se puede asignar como un solo hilo o como varios hilos. Veremos en este tutorial cómo realizar múltiples tareas al mismo tiempo y también aprenderemos más sobre subprocesos y sincronización entre subprocesos.

En este tutorial, aprenderemos:

  • ¿Qué es un solo hilo?
  • ¿Qué es el subproceso múltiple en Java?
  • Ciclo de vida del hilo en Java
  • Sincronización de subprocesos de Java
  • Ejemplo de subprocesos múltiples de Java

¿Qué es un solo hilo?

Un solo hilo es básicamente una unidad de procesamiento liviana y más pequeña. Java utiliza subprocesos mediante el uso de una "clase de subproceso".

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

Cuando una aplicación comienza por primera vez, se crea el hilo de usuario. Publique eso, podemos crear muchos hilos de usuario y hilos de demonio.

Ejemplo de un solo hilo:

paquete demotest;clase pública GuruThread{public static void main (String [] args) {System.out.println ("Hilo único");}}

Ventajas de un solo hilo:

  • Reduce la sobrecarga en la aplicación ya que un solo hilo se ejecuta en el sistema
  • Además, reduce el costo de mantenimiento de la aplicación.

¿Qué es el subproceso múltiple en Java?

MULTITHREADING en Java es un proceso de ejecución de dos o más subprocesos simultáneamente para la máxima utilización de la CPU. Las aplicaciones multiproceso ejecutan dos o más subprocesos al mismo tiempo. Por lo tanto, también se conoce como concurrencia en Java. Cada hilo corre paralelo entre sí. Los subprocesos múltiples no asignan un área de memoria separada, por lo tanto, ahorran memoria. Además, el cambio de contexto entre hilos lleva menos tiempo.

Ejemplo de hilo múltiple:

paquete demotest;La clase pública GuruThread1 implementa Runnable{public static void main (String [] args) {Thread guruThread1 = new Thread ("Guru1");Hilo guruThread2 = nuevo Hilo ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Los nombres de los hilos son los siguientes:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@Anularpublic void run () {}}

Ventajas del multihilo:

  • Los usuarios no están bloqueados porque los hilos son independientes y podemos realizar múltiples operaciones a veces
  • Como tales, los subprocesos son independientes, los otros subprocesos no se verán afectados si un subproceso cumple una excepción.

Ciclo de vida del hilo en Java

El ciclo de vida de un hilo:

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

  1. Nuevo
  2. Ejecutable
  3. Corriendo
  4. Espera
  5. Muerto
  1. Nuevo: En esta fase, el hilo se crea usando la clase "Clase de hilo". Permanece en este estado hasta que el programa inicia el hilo. También se le conoce como hilo nacido.
  2. Ejecutable: en esta página, la instancia del hilo se invoca con un método de inicio. El control de subprocesos se le da al programador para finalizar la ejecución. Depende del planificador, si ejecutar el hilo.
  3. En ejecución: cuando el hilo comienza a ejecutarse, el estado cambia a "en ejecución". El planificador selecciona un subproceso del grupo de subprocesos y comienza a ejecutarse en la aplicación.
  4. Esperando: este es el estado en el que un hilo tiene que esperar. Como hay varios subprocesos que se ejecutan en la aplicación, es necesario sincronizarlos. Por lo tanto, un hilo tiene que esperar hasta que se ejecute el otro hilo. Por lo tanto, este estado se denomina estado de espera.
  5. Muerto: este es el estado en el que se termina el hilo. El subproceso está en estado de ejecución y tan pronto como finalizó el procesamiento, estará en "estado muerto".

Algunos de los métodos más utilizados para hilos son:

Método Descripción
comienzo() Este método inicia la ejecución del hilo y JVM llama al método run () en el hilo.
Sueño (int milisegundos) Este método hace que el hilo duerma, por lo tanto, la ejecución del hilo se detendrá durante los milisegundos proporcionados y, después de eso, el hilo comienza a ejecutarse nuevamente. Esta ayuda en la sincronización de los hilos.
getName () Devuelve el nombre del hilo.
setPriority (int newpriority) Cambia la prioridad del hilo.
producir () Hace que el hilo actual se detenga y que se ejecuten otros hilos.

Ejemplo: En este ejemplo, crearemos un hilo y exploraremos los métodos integrados disponibles para los hilos.

paquete demotest;public class thread_example1 implementa Runnable {@Anularpublic void run () {}public static void main (String [] args) {Hilo guruthread1 = nuevo Hilo ();guruthread1.start ();tratar {guruthread1.sleep (1000);} captura (InterruptedException e) {// TODO Bloque de captura generado automáticamentee.printStackTrace ();}guruthread1.setPriority (1);int gurupriority = guruthread1.getPriority ();System.out.println (guruprioridad);System.out.println ("Subproceso en ejecución");}}

Explicación del código:

  • Línea de código 2: Estamos creando una clase "thread_Example1" que está implementando la interfaz Runnable (debe ser implementada por 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 que iniciaremos la ejecución del hilo.
  • Línea de código 7: Aquí estamos creando un nuevo nombre de hilo como "guruthread1" creando una instancia de una nueva clase de hilo.
  • Línea de código 8: usaremos el método "start" del hilo usando la instancia "guruthread1". Aquí el hilo comenzará a ejecutarse.
  • Línea de código 10: Aquí estamos usando el método "sleep" del hilo usando la instancia "guruthread1". Por lo tanto, el hilo permanecerá inactivo 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.
  • Línea de código 15: aquí estamos estableciendo la prioridad del hilo en 1 desde cualquier prioridad que fuera
  • Línea de código 16: Aquí obtenemos 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 en el hilo.

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

Producción:

5 es la prioridad de Thread y Thread Running es el texto que es la salida de nuestro código.

Sincronización de subprocesos de Java

En multiproceso, existe el comportamiento asincrónico 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 es necesario acceder a los recursos compartidos mediante dos o más subprocesos, se utiliza el enfoque de sincronización.

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

En este enfoque, una vez que el hilo llega al interior del bloque sincronizado, ningún otro hilo puede llamar a ese método en el mismo objeto. Todos los subprocesos tienen que esperar hasta que ese subproceso termine el bloque sincronizado y salga de él.

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

Puede redactarse de la siguiente forma:

Sincronizado (objeto){// Bloque de sentencias a sincronizar}

Ejemplo de subprocesos múltiples de Java

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

Ejemplo 1:

GuruThread1.javapaquete demotest;public class GuruThread1 implementa Runnable {/ *** @param argumentos* /public static void main (String [] args) {Thread guruThread1 = new Thread ("Guru1");Hilo guruThread2 = nuevo Hilo ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Los nombres de los hilos son los siguientes:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());}@Anularpublic void run () {}}

Explicación del código:

  • Línea de código 3: hemos tomado una clase "GuruThread1" que implementa Runnable (debe ser implementada por cualquier clase cuyas instancias estén destinadas a ser ejecutadas por el hilo).
  • Línea de código 8: este es el método principal de la clase
  • Línea de código 9: Aquí estamos creando una instancia de la clase Thread y creando una instancia llamada "guruThread1" y creando un hilo.
  • Línea de código 10: Aquí estamos creando una instancia de la clase Thread y creando una instancia llamada "guruThread2" y creando un hilo.
  • Línea de código 11: Estamos comenzando el hilo, es decir, guruThread1.
  • Línea de código 12: Estamos comenzando el hilo, es decir, guruThread2.
  • Línea de código 13: Salida del texto como "Los nombres de subprocesos son los siguientes:"
  • Línea de código 14: Obtener el nombre del hilo 1 usando el método getName () de la clase del hilo.
  • Línea de código 15: Obtener el nombre del hilo 2 usando el método getName () de la clase del hilo.

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

Producción:

Los nombres de los subprocesos se generan aquí como

  • Guru1
  • Guru2

Ejemplo 2:

En este ejemplo, aprenderemos sobre cómo anular los métodos 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.
paquete demotest;public class GuruThread2 {public static void main (String [] args) {// TODO código auxiliar de método generado automáticamenteGuruThread3 threadguru1 = new GuruThread3 ("guru1");threadguru1.start ();GuruThread3 threadguru2 = new GuruThread3 ("guru2");threadguru2.start ();}}clase GuruThread3 implementa Runnable {Hilo guruthread;Private String guruname;GuruThread3 (nombre de la cadena) {guruname = nombre;}@Anularpublic void run () {System.out.println ("Subproceso en ejecución" + guruname);para (int i = 0; i <4; i ++) {System.out.println (i);System.out.println (guruname);tratar {Thread.sleep (1000);} captura (InterruptedException e) {System.out.println ("El hilo ha sido interrumpido");}}}inicio vacío público () {System.out.println ("Subproceso iniciado");if (guruthread == null) {guruthread = nuevo hilo (esto, guruname);guruthread.start ();}}}

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í tomamos 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 siguientes líneas del código) como "threadguru1" y estamos iniciando el hilo.
  • Línea de código 8-9: Aquí estamos creando otra instancia de la clase GuruThread3 (que se crea en las siguientes líneas del código) como "threadguru2" y estamos iniciando el hilo.
  • Línea de código 11: Aquí estamos creando una clase "GuruThread3" que está implementando la interfaz ejecutable (debe ser implementada 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 tipo hilo y otra 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 del hilo) 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 generando el nombre del hilo usando la declaración println.
  • Línea de código 22-31: Aquí estamos usando un bucle for con el contador inicializado a 0, y no debería ser menor que 4 (podemos tomar cualquier número, por lo tanto, aquí el bucle se ejecutará 4 veces) e incrementando el contador. Estamos imprimiendo el nombre del hilo y también haciendo que el hilo duerma durante 1000 milisegundos dentro de un bloque try-catch ya que el método de suspensión generó una excepción marcada.
  • 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 "Subproceso iniciado".
  • Línea de código 36-40: aquí tomamos una condición if para verificar si la variable de clase guruthread tiene valor o no. Si es nulo, entonces estamos creando una instancia usando la clase de hilo que toma el nombre como parámetro (valor para el cual fue asignado en el constructor). Después de lo cual el hilo se inicia usando el método start ().

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

Salida :

Hay dos subprocesos, por lo tanto, obtenemos dos veces el mensaje "Se inició el subproceso".

Obtenemos los nombres del hilo tal como los hemos generado.

Entra en el bucle for donde imprimimos el contador y el nombre del hilo y el contador comienza con 0.

El bucle se ejecuta tres veces y, en el medio, el hilo se duerme durante 1000 milisegundos.

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

Resumen :

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

  • En el subproceso múltiple, los usuarios no están bloqueados ya que los subprocesos son independientes y pueden realizar varias operaciones a la vez
  • Varias etapas del ciclo de vida del hilo son,
    • Nuevo
    • Ejecutable
    • Corriendo
    • Espera
    • Muerto
  • También aprendimos sobre la sincronización entre subprocesos, lo que ayuda a que la aplicación se ejecute sin problemas.
  • El subproceso múltiple facilita muchas más tareas de la aplicación.

Articulos interesantes...