Tutorial de subprocesos múltiples en Java con ejemplos

Cualquier aplicación puede tener múltiples procesos (escenarios). Cada uno de estos procesos se puede asignar como un solo hilo o como varios hilos. En este tutorial veremos cómo realizar varias tareas a la vez y aprenderemos más sobre los hilos y la sincronización entre hilos.

En este tutorial, aprenderemos:

¿Qué es una hebra única?

Es básicamente un hilo de peso ligero y la unidad de procesamiento más pequeña. Java utiliza subprocesos mediante el uso de «Clase de subproceso».

Hay dos tipos de hilo: hilo de usuario y hilo de demonio (Los hilos de demonio se usan cuando queremos limpiar la aplicación y se usan en segundo plano).

Cuando se inicia una aplicación, se crea un hilo de usuario. Publique eso, podemos crear muchos hilos de usuario y hilos de demonio.

Ejemplo de hebra única:

package demotest;

public class GuruThread
{
       public static void main(String[] args) {
              System.out.println("Single Thread");
       }
}

Ventajas de un solo hilo:

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

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

MULTIHILO Java es un proceso de ejecución en dos o más subprocesos simultáneamente para obtener el mayor uso de la CPU. Las aplicaciones multiproceso ejecutan dos o más subprocesos simultáneamente. Por lo tanto, también se llama Concurrencia en Java. Cada hebra corre paralela entre sí. Los subprocesos múltiples no asignan un área de memoria separada, por lo que ahorran memoria. Además, cambiar el contexto entre hilos lleva menos tiempo.

Ejemplo de hilo múltiple:

package demotest;

public class GuruThread1 implements Runnable
{
       public static void main(String[] args) {
        Thread guruThread1 = new Thread("Guru1");
        Thread guruThread2 = new Thread("Guru2");
        guruThread1.start();
        guruThread2.start();
        System.out.println("Thread names are following:");
        System.out.println(guruThread1.getName());
        System.out.println(guruThread2.getName());
    }
    @Override
    public void run() {
    }

}

Ventajas del multihilo:

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

Ciclo de vida de subprocesos en Java

Ciclo de vida del hilo:

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

  1. Nuevo
  2. Ejecutable
  3. Corriendo
  4. Esperando
  5. Muerto
  1. Nuevo: En este paso, el hilo se crea usando una clase «Class Thread». Permanece en esta posición hasta que el programa A partir de la amenaza. También se le llama hilo nacido.
  2. Ejecutable: En esta página, la muestra de hilo se invoca con un método inicial. El control de subprocesos se le da al programador para completar la ejecución. Depende del planificador, si ejecutar el hilo.
  3. Correr: Cuando el hilo comienza a funcionar, el estado cambia a «en ejecución». El planificador selecciona un subproceso del grupo de subprocesos y comienza a operar en la aplicación.
  4. Esperando: Este es el estado en el que un hilo tiene que esperar. Debido a que la aplicación tiene varios subprocesos en ejecución, se requiere la sincronización entre subprocesos. Por lo tanto, un hilo debe 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 hilo está en un estado actual y una vez que se ha completado el procesamiento, está en un «estado muerto».

A continuación, se muestran algunos de los métodos más utilizados para los subprocesos:

Método
Suelte
comienzo () Este método inicia la ejecución del hilo y JVM llama al método run () el hilo.
Sueño (int milisegundos) Este método aumenta el subproceso de suspensión y, por lo tanto, detiene la ejecución del subproceso durante un milisegundo proporcionado y, después de eso, el subproceso comienza a funcionar nuevamente. Esto ayuda a sincronizar los hilos.
getName () Devuelve el nombre del hilo.
setPriority (int newpriority) Cambia la prioridad del hilo.
resultado () Hace que el subproceso actual se detenga y se ejecuten otros subprocesos.

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

package demotest;
public class thread_example1 implements Runnable {
    @Override
    public void run() {
    }
    public static void main(String[] args) {
        Thread guruthread1 = new Thread();
        guruthread1.start();
        try {
            guruthread1.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        guruthread1.setPriority(1);
        int gurupriority = guruthread1.getPriority();
        System.out.println(gurupriority);
        System.out.println("Thread Running");
  }
}

Explicación del código:

  • Línea de código 2: Estamos creando una clase «thread_Example1» que implementa la interfaz Runnable (se debe implementar cualquier clase cuyos hilos estén destinados a ejecutarse).
  • Código de línea 4: Viola el modo actual de la interfaz accesible porque es obligatorio anular ese modo
  • Código de línea 6: Aquí hemos definido el método principal por el cual comenzamos la ejecución del hilo.
  • Línea de código 7: Aquí estamos creando un nuevo nombre de hilo como «guruthread1» agregando instantáneamente una nueva clase de hilo.
  • Código de línea 8: Usaremos el método «inicial» del hilo usando el ejemplo «guruthread1». Aquí es donde el hilo comenzará a ejecutarse.
  • Código de línea 10: Aquí estamos usando el método «sleep» del hilo usando «guruthread1». Por lo tanto, el hilo permanecerá inactivo durante 1000 milisegundos.
  • Código 9-14: Ponemos un modo de suspensión aquí para intentar un bloqueo de detención ya que hay una excepción marcada que ocurre, es decir, Excepción interrumpida.
  • Código de línea 15: Aquí establecemos la prioridad del hilo en 1 de lo que sea
  • Código de línea 16: Aquí obtenemos la prioridad del hilo usando getPriority ()
  • Código de línea 17: Aquí imprimimos el valor obtenido de getPriority
  • Código de línea 18: Aquí estamos escribiendo un texto que tiene un hilo en ejecución.

Cuando ejecute el código anterior, obtendrá el siguiente resultado:

Producción:

La prioridad del hilo es 5 y Thread Run es el texto que es el resultado de nuestro código.

Sincronización de subprocesos de Java

En multiproceso, existe un comportamiento asincrónico de los programas. Si un hilo está escribiendo varios datos y otro hilo está leyendo datos al mismo tiempo, puede crear una inconsistencia en la aplicación.

Cuando es necesario acceder a los recursos compartidos por dos o más hebras, se utiliza el enfoque de sincronización.

Java proporcionó métodos de sincronización para implementar el comportamiento de sincronización.

En este enfoque, una vez que el hilo llega al interior del bloque de sincronización, ningún otro hilo puede llamar a ese método el mismo objeto. Cada hilo debe esperar a que ese hilo se complete y salir del bloque de sincronización.

De esta manera, la sincronización ayuda con la aplicación multitarea. Un subproceso debe esperar hasta que otro subproceso complete la ejecución, pero luego se permite que se ejecuten los otros subprocesos.

Puede redactarse de la siguiente forma:

Synchronized(object)
{  
        //Block of statements to be synchronized
}

Ejemplo Java Multithreading

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

Ejemplo 1:

GuruThread1.java
package demotest;
public class GuruThread1 implements Runnable{

    /**
     * @param args
     */
    public static void main(String[] args) {
        Thread guruThread1 = new Thread("Guru1");
        Thread guruThread2 = new Thread("Guru2");
        guruThread1.start();
        guruThread2.start();
        System.out.println("Thread names are following:");
        System.out.println(guruThread1.getName());
        System.out.println(guruThread2.getName());
    }
    @Override
    public void run() {
    }

}

Explicación del código:

  • Código de línea 3: Hemos construido una clase «GuruThread1» que implementa Runnable (se debe implementar cualquier clase cuyos subprocesos estén destinados a ejecutarse).
  • Código de línea 8: Este es el método principal de la clase.
  • Código de línea 9: Aquí estamos agregando instantáneamente la clase Thread y creando un ejemplo llamado «guruThread1» y creando un hilo.
  • Línea de código 10: Aquí estamos tomando la clase Thread instantáneamente y creando un ejemplo llamado «guruThread2» y creando un hilo.
  • Código de línea 11: Estamos comenzando el hilo, es decir, guruThread1.
  • Código de línea 12: Estamos comenzando el hilo, es decir, guruThread2.
  • Código de línea 13: El texto de salida como «Los nombres de subprocesos son los siguientes:»
  • Código de línea 14: Encuentre el nombre del hilo 1 usando el método getName () de la clase del hilo.
  • Código de línea 15: Encuentre el nombre del hilo 2 usando el método getName () de la clase del hilo.

Cuando ejecute el código anterior, obtendrá el siguiente resultado:

Producción:

Los nombres de subprocesos se generan aquí como

Ejemplo 2:

En este ejemplo, aprenderemos sobre los métodos de anulación de ejecución () y modo de arranque () de una interfaz accesible y crearemos dos hebras de esa clase y las ejecutaremos en consecuencia.

Además, estamos tomando dos clases,

  • Uno que hará que la interfaz sea accesible y
  • Otro que tendrá el método principal y se ejecutará en consecuencia.
package demotest;
public class GuruThread2 {

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  GuruThread3 threadguru1 = new GuruThread3("guru1");
  threadguru1.start();
  GuruThread3 threadguru2 = new GuruThread3("guru2");
  threadguru2.start();
 }
}
class GuruThread3 implements Runnable {
 Thread guruthread;
 private String guruname;
 GuruThread3(String name) {
  guruname = name;
 }
 @Override
 public void run() {
  System.out.println("Thread running" + guruname);
  for (int i = 0; i < 4; i++) {
   System.out.println(i);
   System.out.println(guruname);
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    System.out.println("Thread has been interrupted");
   }
  }
 }
 public void start() {
  System.out.println("Thread started");
  if (guruthread == null) {
   guruthread = new Thread(this, guruname);
   guruthread.start();
  }

 }
}


Explicación del código:

  • Línea de código 2: Aquí estamos tomando la clase «GuruThread2» que será el modo principal.
  • Línea de código 4: Aquí tomamos un método principal de la clase.
  • Código en línea 6-7: Aquí estamos creando un ejemplo de una clase GuruThread3 (creada debajo de las líneas del código) como «threadguru1» y estamos comenzando el hilo.
  • Código de línea 8-9: Aquí estamos creando otro ejemplo de la clase GuruThread3 (creado debajo de las líneas del código) como «threadguru2» y estamos comenzando el hilo.
  • Código de línea 11: Aquí estamos creando una clase «GuruThread3» que implementa la interfaz accesible (se debe implementar cualquier clase cuyos subprocesos estén destinados a implementarse).
  • Código en línea 13-14: estamos asumiendo dos variables de clase de las cuales una es de tipo hilo y otra de tipo cable.
  • Código de línea 15-18: estamos violando el constructor GuruThread3, que toma un argumento como un tipo de cables (es decir, el nombre del hilo) asignado a una clase de variable guruname y, por lo tanto, se almacena el nombre del hilo.
  • Línea de código 20: Aquí anulamos el modo de ejecución () de la interfaz accesible.
  • Código de línea 21: Generamos el nombre del hilo usando una declaración println.
  • Código de línea 22-31: Aquí estamos usando un ciclo de ciclo con un contador de arranque a 0, que no debe ser menor que 4 (podemos construir cualquier número, así que aquí el ciclo se ejecutará 4 veces) y aumentar el contador. Imprimimos el nombre del hilo y hacemos que el hilo duerma durante 1000 milisegundos dentro de un bloque de intento de captura mientras se marca una excepción del modo de espera.
  • Código de línea 33: Aquí vemos el modo inicial predominante de la interfaz ejecutable.
  • Código de línea 35: Estamos generando el texto «Subproceso iniciado».
  • Código en línea 36-40: Aquí tomamos una condición para verificar si hay un valor o no. Si es nulo, estamos creando un ejemplo usando una clase de hilo que toma el nombre como parámetro (asignándole un valor en el constructor). Después de que el hilo comience a usar el método de arranque ().

Cuando ejecute el código anterior, obtendrá el siguiente resultado:

Producción:

Hay dos subprocesos, por lo que recibimos un mensaje dos veces «Subproceso iniciado».

Obtenemos los nombres de los subprocesos a medida que los mostramos.

Entra en un ciclo donde imprimimos el contador y el nombre del hilo y el contador y comienza con 0.

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

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

Resumen:

En este tutorial, analizamos las aplicaciones multilingües en Java y cómo utilizar subprocesos únicos y múltiples.

  • En el subproceso múltiple, los usuarios no están bloqueados porque los subprocesos son independientes y pueden realizar varias operaciones a la vez
  • Las etapas del ciclo de vida del hilo son diferentes,
    • Nuevo
    • Ejecutable
    • Corriendo
    • Esperando
    • Muerto
  • También aprendimos sobre la sincronización entre subprocesos, lo que ayuda a que la aplicación funcione sin problemas.
  • El subproceso múltiple facilita mucho las tareas de la aplicación.

Deja un comentario

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

Salir de la versión móvil