¿Cuáles son los métodos de implementación de subprocesos múltiples en Java y cómo utilizarlos?
Creación e inicio de subprocesos múltiples en Java
La creación de subprocesos en Java es común en tres formas básicas
1. Heredar la clase Thread y reescribir la. método run() de la clase.
Copiar código
1 clase MyThread extiende el hilo {
2
3 private int i = 0;
4?
5 @Override
6 public void run() {
7 for (i = 0; i < 100; i++) { p>
8 System.out.println(Thread.currentThread().getName() + " " + i);
9 }
10 }
11 }
Copiar código
Copiar código
1 clase pública ThreadTest {
2?
3 public static void main(String[] args) {
4 for (int i = 0; i < 100; i++) {
5 System.out.println(Thread .currentThread().getName() + " " + i);
6 if (i == 30) {
7 Hilo myThread1 = new MyThread() // Crear; ¿Un nuevo hilo?myThread1?Este hilo entra en el nuevo estado
8 Thread myThread2 = new MyThread() // Crea un nuevo hilo myThread2 Este hilo entra en el nuevo estado
9 myThread1 .start(); // Llama al método start() para que el hilo entre en estado listo
10 myThread2.start() // Llama al método start() para que el hilo entre en estado listo. estado
11 }
12 }
13 }
14 }
Copiar el código
Como se muestra arriba, heredar La clase Thread define una nueva clase de subproceso MyThread anulando el método run(). El cuerpo del método run() representa la tarea que el subproceso debe completar, que se denomina subproceso. organismo de ejecución. Cuando se crea este objeto de clase de subproceso, se crea un nuevo subproceso y entra en el nuevo estado del subproceso. Al llamar al método start () al que hace referencia el objeto del subproceso, el subproceso ingresa al estado listo. En este momento, es posible que el subproceso no se ejecute de inmediato, según el tiempo de programación de la CPU.
2. Implemente la interfaz Runnable y reescriba el método run() de la interfaz. El método run() también es el cuerpo de ejecución del hilo. Cree una instancia de la clase de implementación Runnable y use esta instancia como. Clase de subproceso objetivo para crear un objeto de subproceso, que es el objeto de subproceso real.
Copiar código
1 clase MyRunnable implementa Runnable {
2 private int i = 0;
3?
4 @Override
5 public void run() {
6 for (i = 0; i < 100; i++) {
7 System. out.println(Thread.currentThread().getName() + " " + i);
8 }
9 }
10 }
Copiar código
Copiar código
1 clase pública ThreadTest {
2?
3 pública estática vacía principal (Cadena [] args) {
4 for (int i = 0; i < 100; i++) {
5 System.out.println(Thread.currentThread().getName() + " " + i);
6 if (i == 30) {
7 Runnable myRunnable = new MyRunnable() // Crea un objeto de clase de implementación Runnable p> p>
8 Hilo thread1 = new Thread(myRunnable); // Crea un nuevo hilo usando myRunnable como destino del hilo
9 Thread thread2 = new Thread(myRunnable);
10 thread1.start(); // Llama al método start() para hacer que el hilo entre en estado listo
11 thread2.start();
12 }
13 }
14 }
15 }
Copiar código
Creo que todo el mundo está familiarizado con el Los dos métodos anteriores para crear nuevos subprocesos. Entonces, ¿cuál es la relación entre Thread y Runnable? Veamos primero el siguiente ejemplo.
Copiar código
1 clase pública ThreadTest {
2?
3 public static void main(String[] args) {
4 for (int i = 0; i < 100; i++) {
5 System.out.println(Thread.currentThread().getName() + " " + i) ;
6 if (i == 30) {
7 Ejecutable myRunnable = new MyRunnable();
8 Hilo hilo = new MyThread(myRunnable);
9 thread.start();
10 }
11 }
12 }
13 }
14?
15 clase MyRunnable implementa Runnable {
16 private int i = 0;
17?
18 @Override
19 public void run() {
20 System.out.println("en MyRunnable run");
21 para ( i = 0; i < 100; i++) {
22 System.out.println(Thread.currentThread().getName() + " " + i);
23 }
24 }
25 }
26?
27 clase MyThread extiende el hilo {
28?
29 private int i = 0;
30
31 public MyThread(Ejecutable ejecutable){
32 super(ejecutable);
33 }
34?
35 @Override
36 public void run() {
37 Sistema .out.println("en ejecución MyThread");
38 for (i = 0; i < 100; i++) {
39 System.out.println(Thread.currentThread ().getName() + " " + i);
40 }
41 }
42 }
Copiar código
De manera similar, es similar a la forma de crear un hilo implementando la interfaz Runnable, pero la diferencia es que
1 Thread thread = new MyThread(myRunnable);
De esta manera, ¿se puede crear un nuevo hilo correctamente? La respuesta es sí.
En cuanto al cuerpo de ejecución del hilo en este momento, ¿es el método run () en la interfaz MyRunnable o el método run () en la clase MyThread? A través del resultado, sabemos que el cuerpo de ejecución del hilo es el método run() en la clase MyThread. De hecho, la razón es muy simple, porque la propia clase Thread también implementa la interfaz Runnable, y el método run () se definió por primera vez en la interfaz Runnable.
1 interfaz pública ejecutable {
2
3 ejecución nula abstracta pública();
4
5 }
Echemos un vistazo a la implementación del método run() en la interfaz Runnable en la clase Thread:
Copiar código
@Override
public void run() {
if (objetivo!= nulo) {
objetivo.run();
} p>
}
Copiar código
En otras palabras, cuando se ejecuta el método run() en la clase Thread, primero determinará si el objetivo existe y si existe, se ejecutará run() en el método de destino, es decir, el método run() en una clase que implementa la interfaz Runnable y anula el método run(). Sin embargo, en el ejemplo anterior, debido a la existencia de polimorfismo, el método run() en la clase Thread no se ejecuta en absoluto, pero el método run() en el tipo de tiempo de ejecución, es decir, la clase MyThread, se ejecuta directamente. ejecutado primero.
3. Utilice interfaces invocables y futuras para crear hilos. Específicamente, cree una clase de implementación de la interfaz invocable e implemente el método clam(). Y use la clase FutureTask para envolver el objeto de la clase de implementación Callable y use este objeto FutureTask como destino del objeto Thread para crear un hilo.
Parece un poco complicado, pero quedará claro si miras un ejemplo directamente.
Copiar código
1 clase pública ThreadTest {
2?
3 public static void main(String[] args) {
4?
5 Callable
6 FutureTask
7?
8 for (int i = 0; i < 100; i++) {
9 System.out.println(Thread.currentThread().getName() + " " + i);
10 if (i == 30) {
11 Hilo = new Thread(ft); ? //El objeto FutureTask se utiliza como destino del objeto Thread para crear un nuevo hilo
12 thread.start() ?//El hilo entra en estado listo.
13 }
14 }
15?
16 System.out.println("El hilo principal para la ejecución del bucle está completo ..");
17
18 try {
19 int sum = ft.get(); //Obtener el resultado devuelto por la llamada( ) método en el nuevo hilo recién creado
p>20 System.out.println("sum = " + sum);
21 } catch (InterruptedException e) {
22 e.printStackTrace();
23 } captura (ExecutionException e) {
24 e.printStackTrace();
25 }
26?
27 }
28 }
29?
30?
31 clase MyCallable implements Callable 32 private int i = 0; 33? 34 // A diferencia del método run(), el método call() tiene un valor de retorno 35 @Override 36 public Integer call() { 37 int sum = 0; 38 para (; i < 100; i++ ) { 39 System.out.println(Thread.currentThread().get Nombre() + " " + i); 40 suma += i; 41 } 42 devolución suma; 43 } 44? 45 } Copiar código En primer lugar, descubrimos que al implementar la interfaz Callable, no No es más el método run(), sino el método call(). ¡Este método call() sirve como cuerpo de ejecución del hilo y también tiene un valor de retorno! Al crear un nuevo hilo, FutureTask envuelve el objeto MyCallable y sirve como destino del objeto Thread. Luego eche un vistazo a la definición de la clase FutureTask: 1 public class FutureTask 2 3 // .... 4 5 } 1 interfaz pública RunnableFuture 2 3 void run(); 4 5 } Entonces, descubrimos que la clase FutureTask en realidad implementó tanto Interfaces Runnable y Future, lo que hace que tenga las características duales de Future y Runnable. A través del atributo Runnable, se puede utilizar como destino del objeto Thread, y el atributo Future le permite obtener el valor de retorno del método call () en el hilo recién creado. Después de ejecutar este programa, encontramos que suma = 4950 es siempre la última salida. Es probable que el "hilo principal para la ejecución del bucle completado..." se genere en medio del bucle del subproceso secundario. Por el mecanismo de programación de subprocesos de la CPU, sabemos que no hay ningún problema con el tiempo de salida de "el subproceso principal para el bucle ha completado la ejecución ...", entonces, ¿por qué suma = 4950 siempre sale al final? La razón es que cuando el valor de retorno del método call() del subproceso se obtiene a través del método ft.get(), cuando el método del subproceso no ha completado la ejecución, el ft.get El método () se bloqueará hasta que se llame. El valor de retorno no se puede obtener hasta que se ejecute el método (). Lo anterior explica principalmente tres métodos comunes de creación de subprocesos. Para el inicio del subproceso, se debe llamar al método start () del objeto del subproceso: no se puede usar el mismo objeto de subproceso dos veces. el método inicio(). Hola, esta pregunta ha sido respondida. Si estás satisfecho Haz clic en "Aceptar respuesta" en la esquina inferior derecha.