La interrupción del hilo de Java es volátil en vivo

1.1 Resumen

  1. Comprender cómo se implementan las interrupciones de Java
  2. Comprender qué son las excepciones y cómo usarlas con
    interrupciones
  3. Comprender cómo terminar hilos
  4. Comprender algunos de los riesgos de los hilos y cómo mitigarlos.

1.2 Obtén una referencia a ti mismo como hilo conductor

Thread.currentThread().interrupt();

1.3 Resumen de métodos

Thread.sleep(1000)

  • Pausa la ejecución del hilo durante 1000 milisegundos

myThread.join()
Interpretación de la función de unión

  • Pausa el hilo actual hasta que myThread haya terminado de ejecutarse
  • En otras palabras, el método run () de myThread ha finalizado
    El método run del hilo A llama a la unión del hilo B. En este momento, el hilo A está bloqueado. El hilo A no continuará la ejecución hasta que el hilo B termine o muera.

myThread.interrupt()

  • enviar una señal de interrupción a myThread
  • Esto establecerá el indicador de interrupción de myThread en verdadero

2.1 ¿Qué es una interrupción?

  1. Una interrupción es una indicación para un hilo de que debe detener lo que está haciendo y hacer algo más.
  2. El programador decide cómo responde un hilo a una interrupción
  3. Un hilo envía una interrupción que invoca interrupt () en el objeto del hilo para ser interrumpido.
  4. Para que el mecanismo de interrupción funcione correctamente, el hilo interrumpido debe soportarlo. (verifique la bandera de interrupción)

2.2 Mecanismo de interrupción

  1. El mecanismo de interrupción se implementa mediante un indicador interno conocido como estado de interrupción.
  2. Invocar una interrupción en un hilo de destino establece esta bandera
  3. Un hilo puede comprobar si hay una interrupción invocando el método estático Thread.interrupted ()
  4. un hilo puede consultar el estado de interrupción de otro usando el isInterrupted () no estático.

2.3 Los dos métodos de interrupción

  • Thread.interrupted()es estático y comprueba si el hilo actual tiene su bandera interrumpida establecida en verdadero.
    • solo funciona para el hilo desde el que se llama
    • El estado de la interrupción se borra automáticamente
  • mythread.isInterrupted()es un método de instancia que comprueba el objeto Thread en el que se llama.
    • Se puede usar para verificar si se interrumpe un hilo diferente
    • Por ejemplo, si (thread2.isInterrupted () == true)…
  • Un error común es mezclar estos dos

2.4 Verifique la bandera de interrupción

MyThread myThread = new MyThread()
if (myThread.isInterrupted())
{
    
    } //Correct syntax
//Example 1
//Doesn’t check the interrupt flag! Just ignores it!
class MyThread extends Thread
{
    
    
    public void run(){
    
    
        for(int i =1;i <=5;i++){
    
    
            System.out.println(i);
        }
    }

    public static void main(String args[]){
    
    
    MyThread t1 = new MyThread();
    t1.start();
    t1.interrupt();
    }
}

??? Recordatorio: tirar salidas directamente

try{
    
    ...}
catch (FileNotFoundException e){
    
    
    System.err.println("FileNotFoundException:" + e.getMessage());
    throw new SampleException(e);
}
catch (IOException e){
    
    
    System.err.println("Caught IOException:" + e.getMessage());
}

2.5 InterruptedException

//Example2 Interrupting a thread that stops working
class MyThread extends Thread{
    
    
    public void run(){
    
    
        try{
    
    
            Thread.sleep(1000);
            System.out.println("Finished!"); //Not printed
        }
        catch(InterruptedException e ){
    
    
            //This doesn't really do anything
            System.out.println("I'm interrupted"); //Printed
            System.exit(-1);
            //This should be used to deal with the exception

        }
    }

    public static void main (String args[]){
    
    
        MyThread t1 = new MyThread();
        t1.start();
        try{
    
    
            t1.interrupt();//Wrong Syntax
        }
        catch(Exception e)
        {
    
    
            System.out.println("Exception handled" +e);
        }
    }
}
  • si el hilo está durmiendo o uniéndose o esperando en otro hilo:

      1. Se lanza InterruptedException
      1. Se borrará el estado interrumpido
        Haga cosas para ordenar y terminar el hilo
  • Restaurando el estado interrumpido

public void run(){
    
     
    while(!Thread.currentThread().isInterrupted())
    {
    
    
        // Doing some heavy operations
        try {
    
    
        Thread.sleep(5000);
        }
        catch(InterruptedException e)
        {
    
    
        Thread.currentThread().interrupt();
        //interrupt again as may need to do something rather than just exit
        }
    }
}

3.Terminación de hilos

3.1 isAlive ()

  1. Se dice que un hilo está vivo (donde isAlive () devuelve verdadero) cuando se ha iniciado y aún no ha muerto .
  2. El método isAlive () devuelve verdadero si el hilo (en el que se llama) aún se está ejecutando y no ha terminado .
  3. La clase Thread viene con un método de instancia isAlive () para determinar si el hilo está en estado nacido o muerto donde llamar a isAlive () devuelve falso .
if(myThread.isAlive())
{
    
    
    //check something  
    //myThread.interrupt();
}

El método que utilizará más comúnmente para esperar a que finalice un hilo se llama join ()

3.2 Terminar un hilo (Resumen de 3 formas)

No tiene ningún comando para forzar la detención de un hilo (en java)

  1. El hilo ha terminado y sale naturalmente .
  2. El mensaje ha sido marcado como daemon (后台程序) hilo . Cuando el hilo principal que creó este hilo termina, este hilo será forzado (有力 地) terminado.
  3. El hilo ha recibido una señal de interrupción mientras realiza su trabajo.
  • Decide no continuar con el trabajo y sale del método run ().
  • También puede decidir ignorar la señal y continuar trabajando.

3.3 Terminar el hilo de forma natural

  • O podría usar un booleano compartido (por ejemplo, por favorFinish)
    • Verifique periódicamente si pleaseFinish está establecido en true
    • Si es cierto, terminar el hilo
      volátil - volátil
class MyThread extends Thread{
    
    
    private volatile boolean pleaseFinish = false;

    public void run(){
    
    
        //Periodically check for pleaseFinish to be  
        //set to true

        //Do something  
        //Finish nturally  
    }
    public void finishThreadPlease(){
    
    
        pleaseFinish = true;
        /*Be careful when using pleaseFinish  

        If thread is in a non-runnable state, setting a stpo flag variable will have no effect
        
        A thread is in a non-runnale state if  
        + Its sleep method is invoked.
        + The thread calls the wait method to wait for a specific condition to be satisfied.  
        + The thread is blocking on I/O

        */
    }
}

3.4 Hilos de demonio

  • No se puede iniciar y luego demonizarlo.
  • myThread.setDaemon (falso)
    El subproceso del trabajador continúa ejecutándose después de que el subproceso principal ha terminado.

  • myThread.setDaemon (true) El
    hilo de trabajo termina cuando el hilo principal termina.

public void run(){
    
    
    WorkerThread t1 = new WorkerThread();
    t1.setDaemon(true);
    t1.start();
    //do sth  
    //this thread completes
    //When this thread completes:
    //t1 will also be terminated(automatically)
}

3.5 Interrumpir el hilo

Debe capturar una InterruptedException y luego detener el hilo

public void run()
{
    
    
    for (int i = 0; i < importantInfo.length; i++)
    {
    
    
        try {
    
     Thread.sleep(4000); }
        catch (InterruptedException e)
        {
    
    return; }
    System.out.println(importantInfo[i]);
    }
}

Compruebe de forma rutinaria si hay interrupciones en puntos estratégicos donde pueda detenerse y limpiar de forma segura

if (Thread.currentThread.isInterrupted())
{
    
    // cleanup and stop execution
return;
}
public class InterruptThread {
    
    
public static void main(String[] args) {
    
    
Thread thread1 = new Thread(new WaitRunnable());
thread1.start();
try {
    
     Thread.sleep(1000); } // wait a second to make sure thread1 started
catch (InterruptedException e) {
    
     e.printStackTrace(); }
thread1.interrupt(); } // now interrupt thread1

Ejemplo de que el estado interrumpido se ha establecido en falso.

private static class WaitRunnable implements Runnable {
    
    
@Override
public void run() {
    
    
System.out.println("Current time millis : " + System.currentTimeMillis());
try {
    
     Thread.sleep(5000); } // will be asleep when interrupt comes
catch (InterruptedException e) {
    
    
System.out.println("The thread has been interrupted");

System.out.println("The thread is interrupted : " + Thread.interrupted(); // the interrupted status has been set to false}

System.out.println("Current time millis :+ System.currentTimeMillis()); } } }

4.1 Volátil

  • Volátil se usa para indicar que el valor de una variable será
    modificado por diferentes subprocesos
  • El acceso a la variable solo se otorga a un hilo a la
    vez
    public volatile int counter = 0;

4.2 Trampas comunes con volátiles

Array
Si declara arr [] como volátil, eso significa que

  1. la referencia a la matriz es volátil;
  2. los accesos de campo individuales (por ejemplo, arr [5]) no son seguros para subprocesos

Las operaciones unarias
(++, ‐‐) no son atómicas

volatile int i; 
... 
i += 5; //NOT SAFE

4.3 Uso: Detener el almacenamiento en caché

Si se modifica una variable, la caché de otro hilo puede quedar desactualizada
Si configura una variable como volátil:

  1. El valor de esta variable nunca se almacenará en caché a nivel local.
  2. Todas las lecturas y escrituras irán directamente a la "memoria principal";
public class StoppableTask extends Thread {
    
    
private boolean pleaseStop; 
// private volatile boolean pleaseStop
//Because of volatile while loop cannot cache  
// Re-checks pleaseStop every iteration
public void run() {
    
    
    // While loop caches pleaseStop variable 
    //This loop will never end
    while (!pleaseStop)  {
    
     // do some stuff... } }
public void tellMeToStop()
    {
    
     pleaseStop = true; } }

4.4 Cuándo no usar volátiles

  1. Campos que se declararon definitivos (nunca cambian)
  2. Variables a las que accede un solo hilo
  3. Operaciones complejas (incluso cosas como x = x + 5)

4.5 En otro punto: Thread.yield () puede ser mejor que Thread.sleep ()

  1. yield detiene la ejecución continua del hilo y devuelve algo de tiempo al sistema operativo.
  2. rendimiento simplemente renuncia al turno del hilo y lo recupera en
    la siguiente ronda.
  3. sleep () tiene una sobrecarga ligeramente mayor porque crea un sistema que incluye algún tipo de temporizador que activará el proceso. (Depende básicamente de la implementación)
    Por lo tanto, el rendimiento a veces es mejor

Deberes

  1. Crea varios hilos diferentes
    1. Uno que constantemente imprime hola
    2. Uno que imprime en bucle hola con un segundo de suspensión entremedio
  2. ¡Interrumpa los hilos y vea qué pasa!
  3. Agregue soporte de interrupción en ellos para que pueda detenerlos
    con una interrupción
  4. Cree una variable compartida, por favor, finalice para terminar el hilo
    1. Pruebe con y sin volátiles ...

Supongo que te gusta

Origin blog.csdn.net/GreatSimulation/article/details/108818590
Recomendado
Clasificación