Directorio de artículos
1. Inicio del hilo
Hay dos formas de iniciar un hilo, a saber, heredar la clase Thread y reescribir la interfaz Runable, de la siguiente manera:
1.1 、 Hilo
Con respecto a la creación de subprocesos por Thread, la función de creación de subprocesos en subprocesos múltiples de Java ya se ha introducido, por lo que no entraré en detalles aquí.
1.2 、 Ejecutable
En realidad, no existe una diferencia esencial entre Runnable y Thread, que es la diferencia entre interfaz y clase. Reescribir Runnbale aún necesita iniciar el hilo a través de Thread.
En uso, debido a que Java no permite la herencia múltiple, Runnable puede evitar los problemas causados por la limitación de la herencia única.
1.3、Invocable
Dado que la interfaz Runnable no tiene valor de retorno, si se requiere un valor de retorno en algunos escenarios, entonces se debe utilizar la interfaz Callable.
public class App {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
new Thread(futureTask).start();
System.out.println(futureTask.get());
}
}
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "success";
}
}
Se ejecuta con la ayuda de FutureTask
la clase, y la clase FutureTask implementa las interfaces Future y Runnable al mismo tiempo, por lo que puede ser ejecutado por subprocesos como Runnable y también puede usarse como Future para obtener el valor de retorno de un invocable.
Cabe señalar que al obtener el valor de retorno FutureTask.get()
se utiliza un método de bloqueo, una vez que se llama a este método, el código posterior se bloqueará y la ejecución solo podrá continuar después de que se ejecute el método invocable.
En segundo lugar, la suspensión del hilo.
A menudo puede ser necesario detener un hilo. suspend()
Hay , y otros métodos en la API de Java , y sus funciones son suspender el hilo resume()
, reanudar la ejecución del hilo y finalizar el hilo.stop()
Sin embargo, se descubre que estos tres métodos ya no se recomiendan, porque los tres métodos realizan operaciones inmediatas en nuestros subprocesos. Por ejemplo, los métodos stop()
detendrán suspend()
y suspenderán inmediatamente nuestros subprocesos, pero los recursos en los subprocesos no se liberarán. puede causar un problema de bloqueo del programa.
2.1, métodos de interrupción () e isInterrupted ()
Un hilo no debe ser interrumpido o detenido por la fuerza por otros hilos, sino que debe ser detenido por el propio hilo. Por lo tanto, puede usar interrupt()
el método para notificar al subproceso que debe interrumpirse, pero el subproceso notificado debe manejar si interrumpir o continuar ejecutándose.
Llamar al método de interrupción() solo establecerá el indicador de interrupción del hilo en verdadero, no forzará una interrupción. Al mismo tiempo, Java también proporciona un método para consultar si el hilo está interrumpido isInterrupted()
y un método estático Thread.interrupted()
. La diferencia es que el método estático establecerá el estado en falso después de consultar el estado interrumpido de nuestro hilo.
En las siguientes pruebas, se puede encontrar que el método estático Thread.interrupted () que consulta si el hilo está interrumpido cambia el indicador de interrupción a falso. Además, el hilo principal se usa directamente para verlo aquí. Si un Se crea un nuevo hilo para realizar pruebas. Primero debe iniciar el hilo y mantenerlo en ejecución; de lo contrario, la consulta debe ser falsa.
Además, no se recomienda personalizar un indicador de cancelación para suspender la ejecución del hilo. Porque cuando hay bloqueo en el método run(), no se puede detectar el indicador de cancelación personalizado y el hilo debe regresar de la llamada de bloqueo antes de verificar el indicador de cancelación.
2.2, excepción de excepción interrumpida
Si un subproceso está en un estado bloqueado (por ejemplo, el subproceso llama a thread.sleep(), thread.join(), thread.wait(), etc.) y se llama al método de interrupción para interrumpir la operación, se produce una excepción InterruptedException. Se lanzará, pero Inmediatamente después de que se lanza una excepción, el bit de indicador de interrupción del hilo se borra, es decir, se restablece a falso.
Entonces estamos en la excepción InterruptedException, si confirmamos que el hilo necesita ser interrumpido, aquí debemos configurar nuestro indicador de interrupción nuevamente.
2.3 、 tarea futura
El FutureTask que implementa la interfaz Future también nos proporciona otros métodos de interrupción, como por ejemplo cancel()
enviar una señal de interrupción.
Además, la clase FutureTask también proporciona isDone()
y isCancelled()
, que se utilizan para juzgar si la tarea se completa y si se cancela, respectivamente.
- cancelar (booleano): la tarea se cancela y devuelve verdadero; de lo contrario, falso
- cancelar (verdadero): interrumpirá la tarea en ejecución
- cancelar (falso): no interrumpirá las tareas que ya se están ejecutando
- isDone (): si la tarea se completa, si finaliza normalmente, finaliza de forma anormal o se cancela, devuelve verdadero
- isCancelled(): si la tarea se canceló antes de completarse