Requisito previo: diferentes enfoques para la programación concurrente en Java
Clase interna que implementa Runnable
- En este enfoque, el usuario coloca físicamente la definición de clase de la clase que implementa Runnable dentro de la definición de clase de la clase principal.
public class OuterClass{ private class InnerClass implements Runnable{ public void run(){ } } }
- Luego, el método run() se coloca dentro de la clase interna y se pasa al método de ejecución. Ejecutar no significa realmente ejecutar. Significa disponible para ejecución. Por ejemplo, si el usuario tiene un tamaño de grupo de 5 y hay 10 tareas en la cola de tareas, la sexta no comienza a ejecutarse hasta que finaliza una de las primeras cinco.
taskList.execute(new InnerClass());
Implementación práctica:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; // Java Program to depict Concurrent // Programming in action public class OuterClass { // Driver method public static void main(String[] args) { new OuterClass().startThreads(); } // Starts the threads and calls run method // method of the runnable interface private void startThreads() { ExecutorService taskList = Executors.newFixedThreadPool(2); taskList.execute(new InnerClass(1)); taskList.execute(new InnerClass(2)); taskList.execute(new InnerClass(3)); taskList.execute(new InnerClass(4)); taskList.execute(new InnerClass(5)); taskList.shutdown(); } // Pauses execution allowing time for // system to switch back and forth private void pause(double seconds) { try { Thread.sleep(Math.round(1000.0 * seconds)); } catch (InterruptedException e) { e.printStackTrace(); } } // Inner Class public class InnerClass implements Runnable { private int loopLimit; // Constructor to define // different limits InnerClass(int loopLimit) { this.loopLimit = loopLimit; } // Prints thread name and value // of the counter variable @Override public void run() { for (int i = 0; i < loopLimit; i++) { System.out.println( Thread.currentThread().getName() + " Counter: " + i); pause(Math.random()); } } } }
Producción:
pool-1-thread-1 Counter: 0 pool-1-thread-2 Counter: 0 pool-1-thread-1 Counter: 0 pool-1-thread-2 Counter: 1 pool-1-thread-1 Counter: 1 pool-1-thread-2 Counter: 0 pool-1-thread-2 Counter: 1 pool-1-thread-1 Counter: 2 pool-1-thread-1 Counter: 0 pool-1-thread-2 Counter: 2 pool-1-thread-1 Counter: 1 pool-1-thread-2 Counter: 3 pool-1-thread-1 Counter: 2 pool-1-thread-1 Counter: 3 pool-1-thread-1 Counter: 4
ventajas:
- Es fácil acceder a la aplicación principal porque los métodos de las clases internas pueden acceder a cualquier método público o privado oa las variables de instancia de la clase externa.
- Al igual que con las clases separadas, el usuario puede pasar argumentos al constructor que los almacena en las variables de instancia que se ejecutan.
Desventajas:
- Existe una desventaja del acoplamiento estrecho ya que el método de ejecución está estrechamente relacionado con esta aplicación. El método de ejecución no se puede reutilizar en ningún otro lugar.
- Existe un grave peligro de condiciones de carrera. Las clases internas se utilizan específicamente cuando el usuario desea acceder a los datos compartidos (datos en la aplicación principal).
Clase interna anónima que implementa Runnable
Clases internas anónimas: las clases internas se usan con tanta frecuencia en las aplicaciones que los desarrolladores a menudo desean acortar la sintaxis mediante el uso de clases internas anónimas, en las que el usuario da la definición de clase e instancia la clase de una sola vez. Dado que las clases internas anónimas son clases internas, tienen las mismas ventajas que las clases internas, pero son más breves y concisas. Las desventajas que vienen con ellos son que son un poco más confusos para los principiantes, no hay constructores y no se pueden reutilizar en otros lugares.
Implementación práctica:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; // Concurrent programming using // Anonymous Inner Class public class MyClass { // Driver method public static void main(String[] args) { new MyClass().startThreads(); } // Starting threads with pool size as 2 private void startThreads() { ExecutorService taskList = Executors.newFixedThreadPool(2); for (int i = 0; i < 5; i++) { int finalI = i + 1; // Giving the class definition // and instantiating it all at once taskList.execute(new Runnable() { // Prints thread name and value // of the counter variable @Override public void run() { for (int j = 0; j < finalI; j++) { System.out.println( Thread .currentThread() .getName() + " Counter:" + j); pause(Math.random()); } } }); } taskList.shutdown(); } // Pauses execution allowing time for // system to switch back and forth private void pause(double seconds) { try { Thread.sleep( Math.round(1000.0 * seconds)); } catch (InterruptedException e) { e.printStackTrace(); } } }
Producción:
pool-1-thread-1 Counter:0 pool-1-thread-2 Counter:0 pool-1-thread-2 Counter:1 pool-1-thread-1 Counter:0 pool-1-thread-2 Counter:0 pool-1-thread-1 Counter:1 pool-1-thread-2 Counter:1 pool-1-thread-1 Counter:2 pool-1-thread-2 Counter:2 pool-1-thread-2 Counter:3 pool-1-thread-1 Counter:0 pool-1-thread-1 Counter:1 pool-1-thread-1 Counter:2 pool-1-thread-1 Counter:3 pool-1-thread-1 Counter:4
Publicación traducida automáticamente
Artículo escrito por AnureetKaur y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA