4 Métodos para escribir código multihilo en Java

4 Métodos para escribir código multihilo en Java / Programación

Multi-threading es un método para escribir código para ejecutar tareas en paralelo. Java ha tenido un excelente soporte para escribir código de subprocesos múltiples desde los primeros días de Java 1.0. Las recientes mejoras en Java han aumentado las formas en que se puede estructurar el código para incorporar subprocesos múltiples 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 Java Love GitHub? 4 razones por las que debería alojar su código en BitBucket Love GitHub? 4 razones por las que debe alojar su código en BitBucket Debe pensar dónde desea 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 ... Leer más t.

Método 1: Extendiendo la clase Thread

Java proporciona un Hilo clase que se puede ampliar para implementar el correr() método. Este método run () es donde implementas tu 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 Thread simple que solo duerme durante un intervalo específico como una forma de simular una operación de larga duración.

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

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

MyThread worker = 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.

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

Y aquí está la salida de ejecutar este código. Indica que el diagnóstico del hilo principal se imprime antes de que se ejecute el hilo del trabajador.

[Thread [main, 5, main]] thread [Thread [Thread-0,5, main]] thread threading [Thread [Thread-0,5, main]] thread threadding 

Dado que no hay más declaraciones después de iniciar el subproceso de trabajo, el subproceso principal espera a que finalice el subproceso de trabajo antes de que se cierre el programa. Esto permite que el hilo trabajador complete su tarea..

Método 2: utilizar una instancia de subproceso con un ejecutable

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

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 arriba 

La ventaja de implementar la interfaz Runnable en lugar de extender la clase Thread es que la clase worker ahora puede extender una clase específica del 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 del fruto. Puedes hacerlo teniendo la Papaya clase extender el Fruta clase.

clase pública Fruit // frutas específicas aquí clase pública Papaya extiende Fruit // anulación del comportamiento específico de papaya aquí 

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

la clase pública Papaya extiende los implementos de Fruta Runnable // anula el comportamiento específico de la papaya aquí @ Anular la ejecución de vacío público () // 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 Thread en la creación. Cuando se invoca el método start () del subproceso, la tarea se ejecuta en un subproceso separado.

Papaya papaya = Papaya nueva (); // Establecer propiedades e invocar métodos de papaya aquí. Hilo de rosca = hilo nuevo (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 Ejecutable con ExecutorService

A partir de la versión 1.5, Java proporciona una Servicio de Ejecutor como un nuevo paradigma para crear y administrar subprocesos dentro de un programa. Generaliza el concepto de ejecución de hilos al abstraer 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 subproceso separado para cada tarea. Esto le permite a su programa rastrear y administrar la cantidad de subprocesos que se utilizan para las tareas de los trabajadores.

Supongamos que tiene 100 tareas de trabajador en espera de ser ejecutadas. Si inicia un subproceso por trabajador (como se presentó anteriormente), tendría 100 subprocesos dentro de su programa que podrían provocar cuellos de botella en otras partes dentro del programa. En su lugar, si usa un grupo de subprocesos con, digamos 10 subprocesos asignados previamente, sus 100 tareas serán ejecutadas por estos subprocesos una tras otra para que su programa no esté privado de recursos. Además, estos subprocesos del grupo de subprocesos se pueden configurar para que se cuelguen para realizar tareas adicionales para usted.

Un servicio de ejecución acepta un Ejecutable tarea (explicada anteriormente) y ejecuta la tarea en un momento adecuado. los enviar() El método, que acepta la tarea ejecutable, devuelve una instancia de una clase llamada Futuro, que permite a la persona que llama realizar un seguimiento del estado de la tarea. En particular, la obtener() El método permite a la persona que llama esperar a que se complete la tarea (y proporciona el código de retorno, si corresponde).

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

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

ExecutorService esvc = Executors.newSingleThreadExecutor (); Runnable worker = new 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 más envíos de tareas.

Método 4: un callable utilizado con ExecutorService

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

Un ExecutorService también puede aceptar tareas implementadas como Callable 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 la Callable interfaz. Una tarea costosa y lenta se realiza dentro de la llamada() método.

la clase pública Mango extiende los implementos de Fruta Callable public Integer call () // cómputo costoso aquí devuelve 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 ("La tarea devolvió:" + future.get ()); esvc.shutdown (); 

Qué prefieres?

En este artículo, aprendimos algunos métodos para escribir código de múltiples subprocesos 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, entonces puede implementar el Ejecutable interfaz.
  3. Una instalación más moderna para la creación de hilos es el Servicio de Ejecutor que puede aceptar una instancia ejecutable como una tarea para ejecutar. La ventaja de este método es que puede utilizar un grupo de subprocesos para la ejecución de tareas. Un grupo de subprocesos ayuda a conservar los recursos al reutilizar los subprocesos..
  4. Por último, también puede crear una tarea implementando el Callable interfaz y enviar 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..

Explorar más sobre: ​​Java.