Ejecutores Gestionar la ejecución de subprocesos. En la parte superior del ejecutor, la jerarquía es la interfaz del ejecutor, que se utiliza para iniciar un subproceso. EjecutorServiceExtiende Executor y proporciona métodos que gestionan la ejecución. Hay tres implementaciones de ExecutorService: ThreadPoolExecutor, ScheduledThreadPoolExecutor y ForkJoinPool. java.util.concurrent también define la clase de utilidad Executors, que incluye algunos métodos estáticos que simplifican la creación de varios ejecutores. Relacionadas con los ejecutores están las interfaces Future y Callable. Un futuro contiene un valor que es devuelto por un subproceso después de que se ejecuta. Por lo tanto, su valor se define «en el futuro», cuando finaliza el subproceso. Callable define un hilo que devuelve un valor. En este artículo, aprenderemos sobre ThreadPoolExecutor personalizado en Java.
Primero, analicemos dos conceptos que se han utilizado agresivamente aquí, a saber, el grupo de subprocesos y la cola de bloqueo.
- ThreadPool es un contenedor en el que contiene algunos números de subprocesos. A estos hilos se les asignan algunas tareas. Cuando un subproceso completa su tarea, se le asigna la siguiente tarea. Mientras se trabaja en un entorno de subprocesos múltiples, no es práctico crear nuevos subprocesos individuales para cada nueva tarea, porque la creación de un nuevo subproceso es una sobrecarga para el sistema operativo.
- Una cola de bloqueo es una cola que se bloquea cuando intenta salir de ella y la cola está vacía, si intenta poner en cola elementos en t y la cola ya está llena. Todas las operaciones en la cola de bloqueo son seguras para subprocesos.
Además, los métodos específicos importantes que se implementarán son los siguientes:
Método 1: ejecutar()
Este método está contenido en la interfaz Executor. Esta función ejecuta la tarea dada en algún momento en el futuro. No devuelve nada, por lo que el tipo de devolución de este método es nulo.
Método 2: myNewFixedThreadPool()
Este es un método de fábrica de la clase Executors. Se utiliza para crear un número fijo de subprocesos en el grupo de subprocesos.
- Parámetro: int número de subprocesos
- Tipo de retorno: ExecutorService
Procedimiento:
- Cree una interfaz en la que crearemos un método de ejecución. Este método ejecutará la tarea que se le ha asignado.
- En el código generado anteriormente, hemos implementado una interfaz ejecutable. Estamos imprimiendo el nombre actual del hilo con un retraso de 1000 milisegundos. Estas son las tareas que vamos a ejecutar.
- La clase MyExecutor proporciona un método estático myNewFixedThreadPool en el que pasaremos la cantidad de hilos que queremos crear. Este método le dice al grupo de subprocesos cuántos subprocesos habrá en el grupo de subprocesos. Estos subprocesos ejecutarán tareas hasta que todas las tareas se completen.
- Esta es la clase de grupo de subprocesos personalizados. Esta clase es el corazón de todo el mecanismo. Utiliza dos conceptos importantes LinkedBlockingQueue y Execution class. La clase de ejecución se explica más adelante. Esta clase recibe el recuento de subprocesos del método myNewFixedThreadPool. Todas las tareas que enviamos se almacenan en la cola. Todos los subprocesos obtendrán las tareas de la cola. Enviamos la tarea utilizando el método de ejecución de MyExecuorService.
- La clase de ejecución realiza la tarea muy importante de agregar creando la cantidad de subprocesos que queremos en nuestro grupo de subprocesos. Esta clase es donde estamos definiendo cómo obtener la tarea de LinkedBlockingQueue.
- Finalmente, en esta clase, estamos reuniendo todas las piezas y nuestro conjunto de subprocesos personalizado está listo.
Implementación: aquí estamos pasando algunos subprocesos como 3. El número de tareas es 20 y las ejecutamos utilizando el método de ejecución.
Java
// Java Program to illustrate Concept of // CustomThreadPoolExecutor Executor Framework // Importing LinkedBlockingQueue class from java.util // package import java.util.concurrent.LinkedBlockingQueue; // Interface // Custom interface for which contains execute method interface MyExecutorService { // Method void execute(Runnable r); } // Class 1 // Helper class class MyExecutors { // Member variables of this class int capacity; // Passing the number of threads that // will be in the thread pool static MyExecutorService myNewFixedThreadPool(int capacity) { return new MyThreadPool(capacity); } } // Class 2 // Helper class extending to MyExecutorService interface class MyThreadPool implements MyExecutorService { // Member variables of this class static int capacity; static int currentCapacity; // Creating object of LinkedBlockingQueue class // Declaring object of type Runnable static LinkedBlockingQueue<Runnable> linkedTaskBlockingQueue; // Member variables of this class Execution e; // Method 1 public MyThreadPool(int capacity) { // Member variables of this class // this keyword refers to current instance itself this.capacity = capacity; currentCapacity = 0; // Creating a linked blocking queue which will block // if its empty // and it will perform thread safe operation. linkedTaskBlockingQueue = new LinkedBlockingQueue<Runnable>(); // Creating the object of execution class e = new Execution(); } // Method 2 // @Override public void execute(Runnable r) { // Declaring and adding tasks to // blocking queue using add() method linkedTaskBlockingQueue.add(r); // executeMyMethod() method of Execution class // which will execute the tasks e.executeMyMethod(); } } // Class 3 // Helper class extending Runnable interface class Execution implements Runnable { // Method 1 of this class void executeMyMethod() { // At start the current capacity will be 0 // The another capacity is the number of threads we // want to create so we will increase the current // capacity count after creating each thread it // means that we will create the threads if the // current capacity is less than capacity passed by // us i.e number of threads we want to create. // In this case 3 threads will get created if (MyThreadPool.currentCapacity < MyThreadPool.capacity) { MyThreadPool.currentCapacity++; // Creating object of Thread class Thread t = new Thread(new Execution()); // Starting the thread t.start(); } } // Method 2 of this class // @Override public void run() { // Till it is true while (true) { // Here we are fetching the tasks from the // linkedblocking queue // which we have submitted using execute method // and executing them if (MyThreadPool.linkedTaskBlockingQueue.size() != 0) { MyThreadPool.linkedTaskBlockingQueue.poll() .run(); } } } } // Class 4 // Helper class // Here we are creating a simple task // which is printing current thread name class Mytask implements Runnable { // Method 1 of this class // @Override public void run() { // Try block to check for exceptions try { // Making thread to pause fo a second // using sleep() method Thread.sleep(1000); } // Catch block to check for exceptions catch (InterruptedException e) { // Print the exception scaling ith line number // using printStackTrace() method e.printStackTrace(); } // Print and display the current thread using // currentThread() method by getting thread name // using getName() method System.out.println( "Current Thread :-> " + Thread.currentThread().getName()); } } // Class 5 // Main Class public class ExecutorServiceCustom { // Main driver method public static void main(String[] args) { // Getting the object of MyExcutorService by using // the factory method myNewFixedThreadPool // Passing number of threads as 3 MyExecutorService service = MyExecutors.myNewFixedThreadPool(3); for (int i = 0; i < 20; i++) { // Creating 20 tasks and passing them to execute service.execute(new Mytask()); } Runnable runnableTask = null; } }
Producción:
Current Thread :-> Thread-0 Current Thread :-> Thread-1 Current Thread :-> Thread-2 Current Thread :-> Thread-0 Current Thread :-> Thread-1 Current Thread :-> Thread-2 Current Thread :-> Thread-0 Current Thread :-> Thread-1 Current Thread :-> Thread-2 Current Thread :-> Thread-0 Current Thread :-> Thread-1 Current Thread :-> Thread-2 Current Thread :-> Thread-0 Current Thread :-> Thread-1 Current Thread :-> Thread-2 Current Thread :-> Thread-0 Current Thread :-> Thread-1 Current Thread :-> Thread-2 Current Thread :-> Thread-0 Current Thread :-> Thread-1
Nota: En el resultado anterior, hemos impreso el nombre del hilo como se define en el ejecutable 20 veces, ya que hemos enviado 20 tareas que se describen visualmente a través de un video a continuación.
Publicación traducida automáticamente
Artículo escrito por aniketdalal126 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA