Tutorial de subprocesos múltiples en Java con programa y ejemplos
Cualquier aplicación puede tener múltiples procesos (instancias). Cada uno de estos procesos se puede asignar como un único subproceso o varios subprocesos. Veremos en este tutorial cómo realizar múltiples tareas al mismo tiempo y también aprenderemos más sobre hilos y sincronización entre hilos.
En este tutorial de subprocesos múltiples en Java, aprenderemos:
- ¿Qué es un hilo único?
- ¿Qué es subprocesamiento múltiple en Java?
- Ciclo de vida del subproceso en Java
- Sincronización de subprocesos Java
- Ejemplo de subprocesamiento múltiple de Java
¿Qué es un hilo único?
Un solo hilo en Java es básicamente una unidad de procesamiento ligera y la más pequeña. Java utiliza subprocesos mediante el uso de una "Clase de subproceso".
Hay dos tipos de subprocesos:subprocesos de usuario y subprocesos de daemon. (Los subprocesos daemon se usan cuando queremos limpiar la aplicación y se usan en segundo plano).
Cuando una aplicación comienza por primera vez, se crea un subproceso de usuario. Publica eso, podemos crear muchos subprocesos de usuario y subprocesos de daemon.
Ejemplo de hilo único:
package demotest; public class GuruThread { public static void main(String[] args) { System.out.println("Single Thread"); } }
Ventajas del hilo único:
- Reduce la sobrecarga en la aplicación ya que se ejecuta un solo subproceso en el sistema
- Además, reduce el costo de mantenimiento de la aplicación.
¿Qué es multiproceso en Java?
Multiproceso 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 de subprocesos múltiples 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í. Múltiples subprocesos no asignan áreas de memoria separadas, por lo tanto, ahorran memoria. Además, el cambio de contexto entre subprocesos lleva menos tiempo.
Ejemplo de subprocesos múltiples:
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 de multihilo:
- Los usuarios no están bloqueados porque los subprocesos 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 encuentra una excepción.
Ciclo de vida del subproceso en Java
El ciclo de vida de un hilo:
Ciclo de vida del hilo en Java
Hay varias etapas del ciclo de vida del hilo, como se muestra en el diagrama anterior:
- Nuevo
- Ejecutable
- Correr
- Esperando
- Muerto
- Nuevo: En esta fase, el subproceso se crea utilizando la clase "Clase de subproceso". Permanece en este estado hasta que el programa inicia. la amenaza. También se conoce como hilo nacido.
- Ejecutable: En esta página, la instancia del subproceso se invoca con un método de inicio. El control del subproceso se otorga al planificador para finalizar la ejecución. Depende del programador, si ejecutar el hilo.
- En ejecución: Cuando el subproceso comienza a ejecutarse, el estado cambia al estado "en ejecución". El planificador selecciona un subproceso del grupo de subprocesos y comienza a ejecutarse en la aplicación.
- Esperando: Este es el estado cuando un hilo tiene que esperar. Como hay múltiples subprocesos ejecutándose en la aplicación, existe la necesidad de sincronización entre subprocesos. Por lo tanto, un subproceso tiene que esperar hasta que se ejecute el otro subproceso. Por lo tanto, este estado se conoce como estado de espera.
- Muerto: Este es el estado cuando se termina el subproceso. El subproceso se encuentra en estado de ejecución y, tan pronto como completó el procesamiento, se encuentra en "estado muerto".
Algunos de los métodos comúnmente utilizados para subprocesos son:
Método | Descripción |
---|---|
inicio() | Este método inicia la ejecución del hilo y JVM llama al método run() en el hilo. |
Dormir (int milisegundos) | Este método hace que el subproceso duerma, por lo que la ejecución del subproceso se detendrá durante los milisegundos proporcionados y, después de eso, nuevamente el subproceso comenzará a ejecutarse. Esta ayuda en la sincronización de los hilos. |
getNombre() | Devuelve el nombre del hilo. |
establecerPrioridad(int nuevaprioridad) | Cambia la prioridad del hilo. |
rendimiento () | Hace que el subproceso actual se detenga y otros subprocesos se ejecuten. |
Ejemplo: En este programa de subprocesos múltiples en el ejemplo de Java, vamos a crear un subproceso y explorar los métodos integrados disponibles para los subprocesos.
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 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" instanciando una nueva clase de hilo.
- Línea de código 8: Usaremos el método de "inicio" del hilo usando la instancia "guruthread1". Aquí el hilo comenzará a ejecutarse.
- Línea de código 10: Aquí estamos usando el método de "suspensión" del hilo usando la instancia "guruthread1". Por lo tanto, el subproceso 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 verificada que ocurre, es decir, una excepción interrumpida.
- Línea de código 15: Aquí estamos configurando la prioridad del hilo a 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 el hilo se está ejecutando.
Cuando ejecuta el código anterior, obtiene el siguiente resultado:
Salida:
5 es la prioridad del subproceso y Thread Running es el texto que es la salida de nuestro código.
Sincronización de subprocesos de Java
En multithreading, existe el comportamiento asíncrono de los programas. Si un subproceso está escribiendo algunos datos y otro subproceso está leyendo datos al mismo tiempo, podría crear inconsistencias en la aplicación.
Cuando existe la 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 el comportamiento sincronizado.
En este enfoque, una vez que el subproceso alcanza el interior del bloque sincronizado, ningún otro subproceso 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 termine su ejecución, solo entonces se permite la ejecución de los otros subprocesos.
Se puede escribir de la siguiente forma:
Synchronized(object) { //Block of statements to be synchronized }
Ejemplo de subprocesamiento múltiple de Java
En este ejemplo de subprocesos múltiples de Java, tomaremos dos subprocesos y buscaremos los nombres del subproceso.
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:
- Línea de código 3: Hemos tomado una clase "GuruThread1" que implementa Runnable (debe ser implementado 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 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.
- 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 los subprocesos son los siguientes:"
- Línea de código 14: Obtener el nombre del subproceso 1 usando el método getName() de la clase del subproceso.
- Línea de código 15: Obtener el nombre del subproceso 2 usando el método getName() de la clase del subproceso.
Cuando ejecuta el código anterior, obtiene el siguiente resultado:
Salida:
Los nombres de los hilos se muestran aquí como
- Gurú1
- Gurú2
Ejemplo 2:
En este ejemplo de subprocesos múltiples en Java, aprenderemos a 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.
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 una clase "GuruThread2" que tendrá el método principal.
- 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 siguientes 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 líneas siguientes del código) como "threadguru2" y estamos iniciando el hilo.
- Línea de código 11: Aquí estamos creando una clase "GuruThread3" que implementa 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 tipo 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 subproceso) que se asigna a la variable de clase guruname y, por lo tanto, se almacena el nombre del subproceso.
- 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 instrucción println.
- Línea de código 22-31: Aquí estamos usando un bucle for con un contador inicializado en 0, y no debe ser inferior a 4 (podemos tomar cualquier número, por lo que 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 cuando el método de suspensión generó una 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 "Subproceso iniciado".
- Línea de código 36-40: Aquí estamos tomando una condición if para verificar si la variable de clase guruthread tiene valor o no. Si es nulo, estamos creando una instancia usando la clase de hilo que toma el nombre como parámetro (valor para el cual se asignó en el constructor). Después de lo cual se inicia el hilo usando el método start().
Cuando ejecuta el código anterior, obtiene el siguiente resultado:
Salida :
Hay dos subprocesos, por lo tanto, recibimos dos veces el mensaje "Subproceso iniciado".
Obtenemos los nombres de los subprocesos tal como los hemos generado.
Entra en el ciclo for donde estamos imprimiendo el contador y el nombre del hilo y el contador comienza con 0.
El bucle se ejecuta tres veces y, en el medio, el subproceso se duerme durante 1000 milisegundos.
Por lo tanto, primero, obtenemos guru1, luego guru2 y luego nuevamente guru2 porque el subproceso duerme aquí durante 1000 milisegundos y luego luego guru1 y nuevamente guru1, el subproceso duerme durante 1000 milisegundos, por lo que obtenemos guru2 y luego guru1.
Resumen
En este tutorial, vimos aplicaciones de subprocesos múltiples en Java y cómo usar subprocesos únicos y múltiples en Java.
- Explicar subprocesos múltiples en Java:en subprocesos múltiples, los usuarios no están bloqueados ya que los subprocesos son independientes y pueden realizar múltiples operaciones a la vez
- Varias etapas del ciclo de vida del subproceso son,
- Nuevo
- Ejecutable
- Correr
- Esperando
- Muerto
- También aprendimos sobre la sincronización entre subprocesos, lo que ayuda a que la aplicación funcione sin problemas.
- La programación multiproceso en Java facilita muchas más tareas de aplicación.
Java
- Programa Java Hola Mundo
- Funciones de C++ con ejemplos de programas
- Tutorial de colecciones de C# con ejemplos
- Método Java String indexOf() con subcadena y ejemplos
- Método Java String charAt() con ejemplo
- Método Java String compareTo():cómo usarlo con ejemplos
- Sobrecarga de constructores en Java:qué es y ejemplos de programas
- Programa Java para comprobar el número primo
- Algoritmo de ordenación por inserción en Java con ejemplo de programa
- Clasificación de selección en el programa Java con ejemplo
- Multihilo C++