Requisito previo: diferentes enfoques para la programación concurrente en Java
Veamos el segundo enfoque en detalle.
- El usuario tiene la clase principal que implementa ejecutable , que es una promesa para el compilador de que la clase tendrá un método de ejecución .
public class MyClass implements Runnable{ public void run(){ } }
- Luego, el usuario pasa una referencia a la aplicación principal al método de ejecución utilizando esta palabra clave.
taskList.execute(this)
Esta es la forma de transmitirle al compilador que cuando se ejecuta una tarea en particular, llámelo como el método de ejecución respectivo.
- La ventaja de este enfoque sobre el enfoque uno es que el método de ejecución puede llamar a métodos en la aplicación principal, incluidos los privados.
- La desventaja de este enfoque sobre el primer enfoque son las condiciones de carrera. La razón por la que colocamos el método de ejecución en la aplicación principal es para que pueda manejar datos en la aplicación principal. Si el usuario inicia más de un hilo y están modificando simultáneamente los mismos datos compartidos, entonces hay condiciones de carrera de las que preocuparse. En segundo lugar, no hay un constructor , lo que hace que sea muy difícil pasar los argumentos del constructor, por lo que cada clase comienza de la misma manera.
- Código de muestra: el usuario implementa ejecutable en la clase principal y la misma clase también tiene muchos otros métodos para hacer la cola de tareas y llamar al método de ejecución.
La siguiente es la implementación del enfoque 2 del contraejemplo explicado en el enfoque uno:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; // Concurrent Programming in action public class MainAppRunnable implements Runnable { private final int loopLimit; // Limit till which the counter will run private MainAppRunnable(int loopLimit) { this.loopLimit = loopLimit; } private void startThreads() { // Made the task queue ExecutorService taskList = Executors.newFixedThreadPool(2); // Added these to the task queue // and made available for execution taskList.execute(this); taskList.execute(this); taskList.execute(this); taskList.execute(this); taskList.execute(this); // Stopped new tasks from being // added to the task queue taskList.shutdown(); } @Override public void run() { for (int i = 0; i < loopLimit; i++) { System.out.println( Thread.currentThread().getName() + " Counter: " + i); } // Called private method that is // part of the same application pause(Math.random()); } // Methods that run uses can be private // in this approach private void pause(double seconds) { try { Thread .sleep(Math.round(seconds * 1000.0)); } catch (InterruptedException e) { e.printStackTrace(); } } // Driver method public static void main(String[] args) { new MainAppRunnable(3).startThreads(); } }
Producción:
pool-1-thread-1 Counter: 0 pool-1-thread-2 Counter: 0 pool-1-thread-1 Counter: 1 pool-1-thread-1 Counter: 2 pool-1-thread-2 Counter: 1 pool-1-thread-2 Counter: 2 pool-1-thread-2 Counter: 0 pool-1-thread-2 Counter: 1 pool-1-thread-2 Counter: 2 pool-1-thread-2 Counter: 0 pool-1-thread-2 Counter: 1 pool-1-thread-2 Counter: 2 pool-1-thread-1 Counter: 0 pool-1-thread-1 Counter: 1 pool-1-thread-1 Counter: 2
Publicación traducida automáticamente
Artículo escrito por AnureetKaur y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA