4 métodos para escribir código multiproceso en Java

  • William Charles
  • 0
  • 2786
  • 625
Anuncio

Multi-threading es un método de escribir código para ejecutar tareas en paralelo. Java ha tenido un excelente soporte para escribir código multiproceso desde los primeros días de Java 1.0. Las mejoras recientes en Java han aumentado las formas en que el código puede estructurarse para incorporar múltiples subprocesos en programas Java.

En este artículo, comparamos algunas de estas opciones para que pueda juzgar mejor qué opción usar para su próximo proyecto de Java Love GitHub? 4 razones por las que debe alojar su código en BitBucket Love GitHub? 4 razones por las que debe alojar su código en BitBucket Debe pensar dónde tiene la intención de almacenar su código. Es probable que hayas oído hablar de GitHub. Eso no es sorprendente. GitHub es utilizado por individuos y empresas para alojar código, colaborar en la documentación ... t.

Método 1: extender la clase Thread

Java proporciona un Hilo clase que se puede ampliar para implementar el correr() método. Este método run () es donde implementa su tarea. Cuando desee iniciar la tarea en su propio hilo, puede crear una instancia de esta clase e invocar su comienzo() método. Esto inicia la ejecución del hilo y se ejecuta hasta su finalización (o termina en una excepción).

Aquí hay una clase de subproceso simple que solo duerme durante un intervalo específico como una forma de simular una operación de larga duración.

clase pública MyThread extiende Thread private int sleepFor; Public MyThread (int sleepFor) this.sleepFor = sleepFor;  @Override public void run () System.out.printf ("[% s] thread thread \ n", Thread.currentThread (). ToString ()); pruebe Thread.sleep (this.sleepFor);  catch (InterruptedException ex)  System.out.printf ("[% s] thread thread \ n", Thread.currentThread (). toString ());  

Cree una instancia de esta clase Thread dándole el número de milisegundos para dormir.

MyThread trabajador = nuevo MyThread (sleepFor); 

Inicie la ejecución de este subproceso de trabajo invocando su método start (). Este método devuelve el control inmediatamente a la persona que llama, sin esperar a que el hilo termine.

trabajador.inicio (); System.out.printf ("[% s] hilo principal \ n", Thread.currentThread (). ToString ()); 

Y aquí está el resultado de ejecutar este código. Indica que el diagnóstico del subproceso principal se imprime antes de que se ejecute el subproceso de trabajo.

[Hilo [principal, 5, principal]] hilo principal [Hilo [Hilo-0,5, principal]] comienzo del hilo [Hilo [Hilo-0,5, principal]] final del hilo 

Como no hay más instrucciones después de iniciar el subproceso de trabajo, el subproceso principal espera a que el subproceso de trabajo finalice antes de que el programa salga. Esto permite que el subproceso de trabajo complete su tarea.

Método 2: Usar una instancia de subproceso con un Runnable

Java también proporciona una interfaz llamada Ejecutable que puede ser implementado por una clase trabajadora para ejecutar la tarea en su correr() método. Esta es una forma alternativa de crear una clase de trabajador en lugar de extender el Hilo clase (descrita anteriormente).

Aquí está la implementación de la clase de trabajo que ahora implementa Runnable en lugar de extender Thread.

La clase pública MyThread2 implementa Runnable // igual que el anterior 

La ventaja de implementar la interfaz Runnable en lugar de extender la clase Thread es que la clase trabajador ahora puede extender una clase específica de dominio dentro de una jerarquía de clases.

Qué significa esto?

Digamos, por ejemplo, que tienes un Fruta clase que implementa ciertas características genéricas de las frutas. Ahora quieres implementar un Papaya clase que especializa ciertas características de la fruta. Puedes hacer eso teniendo el Papaya la clase extiende el Fruta clase.

Public class Fruit // detalles de la fruta aquí public class Papaya extiende Fruit // anula el comportamiento específico de papaya aquí 

Ahora suponga que tiene una tarea que requiere mucho tiempo y que Papaya debe soportar, que se puede realizar en un hilo separado. Este caso puede manejarse haciendo que la clase Papaya implemente Runnable y proporcione el método run () donde se realiza esta tarea.

public class Papaya extiende Fruit implements Runnable // anula el comportamiento específico de papaya aquí @Override public void run () // tarea que consume mucho tiempo aquí.  

Para iniciar el subproceso de trabajo, crea una instancia de la clase de trabajo y la entrega a una instancia de subproceso en la creación. Cuando se invoca el método start () del subproceso, la tarea se ejecuta en un subproceso separado.

Papaya papaya = nueva Papaya (); // establece propiedades e invoca métodos de papaya aquí. Hilo de rosca = nuevo hilo (papaya); thread.start (); 

Y ese es un breve resumen de cómo usar un Runnable para implementar una tarea que se ejecuta dentro de un hilo.

Método 3: ejecutar un Runnable con ExecutorService

A partir de la versión 1.5, Java proporciona un Servicio de ejecutor como un nuevo paradigma para crear y administrar hilos dentro de un programa. Generaliza el concepto de ejecución de hilos abstrayendo la creación de hilos.

Esto se debe a que puede ejecutar sus tareas dentro de un grupo de subprocesos tan fácilmente como usar un hilo separado para cada tarea. Esto permite que su programa rastree y administre cuántos subprocesos se utilizan para las tareas de los trabajadores..

Suponga que tiene 100 tareas de trabajador esperando ser ejecutadas. Si inicia un subproceso por trabajador (como se presentó anteriormente), tendría 100 subprocesos dentro de su programa que podrían generar cuellos de botella en otras partes del programa. En cambio, si usa un grupo de subprocesos con, digamos, 10 subprocesos preasignados, sus 100 tareas serán ejecutadas por estos subprocesos uno tras otro para que su programa no tenga pocos recursos. Además, estos subprocesos de grupo de subprocesos se pueden configurar para que se mantengan para realizar tareas adicionales.

Un ExecutorService acepta un Ejecutable (explicado anteriormente) y ejecuta la tarea en el momento adecuado. los enviar() El método, que acepta la tarea Runnable, devuelve una instancia de una clase llamada Futuro, que permite al llamante rastrear el estado de la tarea. En particular, el obtener() El método permite que la persona que llama espere a que se complete la tarea (y proporciona el código de retorno, si corresponde).

En el siguiente ejemplo, creamos un ExecutorService utilizando el método estático. newSingleThreadExecutor (), que, como su nombre indica, crea un solo hilo para ejecutar tareas. Si se envían más tareas mientras se ejecuta una tarea, ExecutorService pone en cola estas tareas para su posterior ejecución.

La implementación Runnable que utilizamos aquí es la misma que se describió anteriormente..

ExecutorService esvc = Executors.newSingleThreadExecutor (); Trabajador ejecutable = nuevo MyThread2 (sleepFor); Futuro futuro = esvc.submit (trabajador); System.out.printf ("[% s] hilo principal \ n", Thread.currentThread (). ToString ()); future.get (); esvc.shutdown (); 

Tenga en cuenta que un ExecutorService debe cerrarse correctamente cuando ya no sea necesario para enviar más tareas.

Método 4: Un invocable utilizado con ExecutorService

A partir de la versión 1.5, Java introdujo una nueva interfaz llamada Invocable. Es similar a la interfaz Runnable anterior con la diferencia de que el método de ejecución (llamado llamada() en vez de correr()) puede devolver un valor. Además, también puede declarar que un Excepción puede ser arrojado.

Un ExecutorService también puede aceptar tareas implementadas como Invocable y devuelve un Futuro con el valor devuelto por el método al finalizar.

Aquí hay un ejemplo Mango clase que extiende el Fruta clase definida anteriormente e implementa el Invocable interfaz. Se realiza una tarea costosa y que lleva mucho tiempo dentro de llamada() método.

public class Mango extiende Fruit implements Callable public Integer call () // el cálculo costoso aquí devuelve un nuevo Integer (0);  

Y aquí está el código para enviar una instancia de la clase a un ExecutorService. El siguiente código también espera a que se complete la tarea e imprime su valor de retorno.

ExecutorService esvc = Executors.newSingleThreadExecutor (); Trabajador MyCallable = nuevo MyCallable (sleepFor); Futuro futuro = esvc.submit (trabajador); System.out.printf ("[% s] hilo principal \ n", Thread.currentThread (). ToString ()); System.out.println ("Tarea devuelta:" + future.get ()); esvc.shutdown (); 

Qué prefieres?

En este artículo, aprendimos algunos métodos para escribir código multiproceso en Java. Éstos incluyen:

  1. Extendiendo el Hilo La clase es la más básica y ha estado disponible desde Java 1.0.
  2. Si tiene una clase que debe extender alguna otra clase en una jerarquía de clases, puede implementar el Ejecutable interfaz.
  3. Una instalación más moderna para crear hilos es la Servicio de ejecutor que puede aceptar una instancia Runnable como una tarea para ejecutar. La ventaja de este método es que puede usar un grupo de subprocesos para la ejecución de tareas. Un grupo de subprocesos ayuda en la conservación de recursos mediante la reutilización de subprocesos.
  4. Por último, también puede crear una tarea implementando el Invocable interfaz y envío de la tarea a un ExecutorService.

¿Cuál de estas opciones crees que usarás en tu próximo proyecto? Háganos saber en los comentarios a continuación.




Nadie ha comentado sobre este artículo todavía.

Sobre tecnología moderna, simple y asequible.
Tu guía en el mundo de la tecnología moderna. Aprenda a usar las tecnologías y los dispositivos que nos rodean todos los días y aprenda a descubrir cosas interesantes en Internet.