Tabla de contenido
1.2.3 Método Thread.interrupted()
1.3 Manejar correctamente las interrupciones
1.4 Dejar de interrumpir subprocesos en ejecución
1. Mecanismo de interrupción
En la programación concurrente, la ejecución de un hilo puede ser interrumpida por otro hilo, esta interrupción se llama "interrupción". La interrupción es un mecanismo de comunicación entre subprocesos que permite que un subproceso notifique a otro subproceso, solicitándole que detenga su trabajo actual y realice algunas otras operaciones. El mecanismo de interrupción en JUC se interrupt()
implementa a través de métodos.
1.1 Principio de interrupción
La interrupción se logra a través del bit indicador de interrupción del subproceso. Cada subproceso de Java tiene un indicador de interrupción booleano asociado. Cuando un subproceso llama interrupt()
a un método, establece el bit indicador de interrupción del subproceso de destino en true
, lo que indica que el subproceso ha sido interrumpido. El subproceso interrumpido puede descubrir la solicitud de interrupción comprobando su propio estado de interrupción.
1.2 Método de interrupción
1.2.1 interrupt()
Método
interrupt()
Los métodos son Thread
métodos de instancia de una clase que se utilizan para interrumpir el subproceso actual o especificar un subproceso de destino. Se declara de la siguiente manera:
public void interrupt()
Llamar interrupt()
al método establecerá el bit indicador de interrupción del subproceso de destino en true
. Si el subproceso de destino está en un estado bloqueado (por ejemplo, llamando a métodos como sleep()
, wait()
, join()
etc.), lanzará inmediatamente InterruptedException
una excepción y regresará del estado bloqueado. Después de que el subproceso se interrumpe en el estado bloqueado y InterruptedException
se lanza una excepción, debemos restaurar el estado interrumpido. Esto se debe a que después de que se lanza la excepción, el indicador de interrupción se borrará.Si queremos que el código posterior detecte el estado de interrupción correctamente, debemos configurar manualmente el indicador de interrupción nuevamente.
catch (InterruptedException e) {
// 恢复中断状态
Thread.currentThread().interrupt();
}
1.2.2 isInterrupted()
Método
isInterrupted()
method es Thread
un método de instancia de la clase que se utiliza para consultar el estado de interrupción del subproceso actual. Se declara de la siguiente manera:
public boolean isInterrupted()
El isInterrupted()
método de llamada devolverá el bit indicador de interrupción del hilo actual. Tenga en cuenta que llamar a este método no borrará el indicador de interrupción.
1.2.3 Thread.interrupted()
Método
Thread.interrupted()
El método es Thread
un método estático de la clase, que se utiliza para consultar el estado de interrupción del subproceso actual y borrar el bit indicador de interrupción. Se declara de la siguiente manera:
public static boolean interrupted()
El Thread.interrupted()
método de llamada devuelve el estado de interrupción del subproceso actual y restablece el bit indicador de interrupción del subproceso actual a false
.
1.3 Manejar correctamente las interrupciones
En el punto clave de la ejecución del subproceso, debemos verificar el estado de interrupción del subproceso y dar la respuesta correspondiente según la situación. Por ejemplo, al ejecutar una tarea en un ciclo, podemos usar isInterrupted()
el método para verificar el estado de interrupción, y cuando encontramos que el hilo se ha interrumpido, podemos terminar el ciclo y salir del hilo a tiempo.
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// 执行任务...
}
}
A veces pasamos el bit indicador de interrupción a otros métodos u objetos.Después de procesar la lógica de interrupción, debemos borrar el estado de interrupción para no afectar los juicios de interrupción posteriores. El método se puede utilizar Thread.interrupted()
para borrar el bit indicador de interrupción.
Thread th = new Thread(() -> {
while (!Thread.interrupted()){
System.out.println(Thread.currentThread().getName());
Thread.currentThread().interrupt();
}
}, "th");
th.start();
1.4 Dejar de interrumpir subprocesos en ejecución
1.4.1 volátil
volatile
Es una palabra clave en Java, utilizada para declarar variables. Su función principal es asegurar que volatile
la variable modificada sea visible para todos los hilos, es decir, cada vez que volatile
se lea la variable, se obtendrá el último valor directamente de la memoria principal en lugar de utilizar el valor de caché local del hilo. En un entorno de subprocesos múltiples, cuando un subproceso modifica volatile
el valor de la variable modificada, el valor se actualizará en la memoria principal inmediatamente, y se notificará a otros subprocesos, y otros subprocesos verán el valor más reciente cuando lean la variable. Esto asegura que las modificaciones a la variable sean visibles para todos los subprocesos. volatile
También puede evitar la reorganización de las instrucciones y garantizar que volatile
las operaciones de lectura y escritura de las variables modificadas estén en orden y que no haya resultados inesperados.
public class Test {
private static volatile boolean key=false;
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
while (true){
if(key){
System.out.println(Thread.currentThread().getName()+ "终止");
break;
}
System.out.println(Thread.currentThread().getName()+" 执行");
}
}).start();
new Thread(()->{
key=true;
}).start();
}
}
1.4.2 Clases atómicas
Las clases atómicas son un conjunto de clases de herramientas proporcionadas por JUC para implementar operaciones atómicas, que garantizan la atomicidad en operaciones específicas. La clase atómica implementa operaciones atómicas a través del algoritmo CAS (Comparar e intercambiar) CAS es una tecnología de bloqueo optimista que puede implementar operaciones simultáneas seguras para subprocesos sin usar bloqueos.
Las clases atómicas comúnmente utilizadas incluyen: AtomicInteger
, AtomicLong
, AtomicBoolean
etc.
public class Test {
private static AtomicBoolean atomicBoolean=new AtomicBoolean(false);
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
while (true){
if(atomicBoolean.get()){
System.out.println(Thread.currentThread().getName()+ "终止");
break;
}
System.out.println(Thread.currentThread().getName()+" 执行");
}
}).start();
new Thread(()->{
atomicBoolean.set(true);
}).start();
}
}
El tercer caso es usar el método de interrupción presentado al principio del artículo. omitido aquí.