📜  在Java中杀死线程

📅  最后修改于: 2022-05-13 01:55:09.618000             🧑  作者: Mango

在Java中杀死线程

当 run() 方法完成时,线程会自动销毁。但可能需要在线程完成其生命周期之前终止/停止线程。以前,方法suspend()resume()stop()用于管理线程的执行。但是这些方法在Java 2 中被弃用了,因为它们可能导致系统故障。现代挂起/停止线程的方法是使用布尔标志和 Thread.interrupt() 方法。

  • 使用布尔标志:我们可以定义一个布尔变量,用于停止/杀死线程说“退出”。每当我们想要停止一个线程时,'exit' 变量将被设置为 true。
Java
// Java program to illustrate
// stopping a thread using boolean flag
 
class MyThread implements Runnable {
 
    // to stop the thread
    private boolean exit;
 
    private String name;
    Thread t;
 
    MyThread(String threadname)
    {
        name = threadname;
        t = new Thread(this, name);
        System.out.println("New thread: " + t);
        exit = false;
        t.start(); // Starting the thread
    }
 
    // execution of thread starts from run() method
    public void run()
    {
        int i = 0;
        while (!exit) {
            System.out.println(name + ": " + i);
            i++;
            try {
                Thread.sleep(100);
            }
            catch (InterruptedException e) {
                System.out.println("Caught:" + e);
            }
        }
        System.out.println(name + " Stopped.");
    }
 
    // for stopping the thread
    public void stop()
    {
        exit = true;
    }
}
 
// Main class
public class Main {
    public static void main(String args[])
    {
        // creating two objects t1 & t2 of MyThread
        MyThread t1 = new MyThread("First  thread");
        MyThread t2 = new MyThread("Second thread");
        try {
            Thread.sleep(500);
            t1.stop(); // stopping thread t1
            t2.stop(); // stopping thread t2
            Thread.sleep(500);
        }
        catch (InterruptedException e) {
            System.out.println("Caught:" + e);
        }
        System.out.println("Exiting the main Thread");
    }
}


Java
// Java program to illustrate non-volatile boolean flag
 
public class Main {
 
    // static used here
    // because a non-static variable
    // cannot be referenced
    // from a static context
 
    // exit variable to stop both
    // the main and inside threads
    static boolean exit = false;
 
    public static void main(String[] args)
    {
        System.out.println("started main thread..");
 
        // a thread inside main thread
        new Thread() {
            public void run()
            {
                System.out.println("started inside thread..");
 
                // inside thread caches the value of exit,
                // so changes made to exit are not visible here
                while (!exit) // will run infinitely
                {
                }
 
                // this will not be printed.
                System.out.println("exiting inside thread..");
            }
        }.start();
 
        try {
            Thread.sleep(500);
        }
        catch (InterruptedException e) {
            System.out.println("Caught :" + e);
        }
 
        // so that we can stop the threads
        exit = true;
        System.out.println("exiting main thread..");
    }
}


Java
// Java program to illustrate volatile boolean flag
 
public class Main {
 
    // static used here because
    // a non-static variable cannot be referenced
    // from a static context
 
    // exit variable to stop both
    // the main and inside threads
    static volatile boolean exit = false;
    public static void main(String[] args)
    {
 
        System.out.println("started main thread..");
 
        // a thread inside main thread
        new Thread() {
            public void run()
            {
 
                // changes made to exit
                // in main thread are visible here
                System.out.println("started inside thread..");
 
                // will not run infinitely
                while (!exit) {
                }
 
                // this will be printed
                System.out.println("exiting inside thread..");
            }
        }.start();
 
        try {
            Thread.sleep(500);
        }
        catch (InterruptedException e) {
            System.out.println("Caught :" + e);
        }
 
        // so that we can stop the threads
        exit = true;
        System.out.println("exiting main thread..");
    }
}


Java
// Java program to illustrate
// stopping a thread
// using the interrupt() method
 
class MyThread implements Runnable {
 
    Thread t;
 
    MyThread()
    {
        t = new Thread(this);
        System.out.println("New thread: " + t);
        t.start(); // Starting the thread
    }
 
    // execution of thread starts from run() method
    public void run()
    {
        while (!Thread.interrupted()) {
            System.out.println("Thread is running");
        }
        System.out.println("Thread has stopped.");
    }
}
 
// Main class
public class Main {
    public static void main(String args[])
    {
        // creating objects t1 of MyThread
        MyThread t1 = new MyThread();
 
        try {
            Thread.sleep(1);
 
            // t1 is an object of MyThread
            // which has an object t
            // which is of type Thread
            t1.t.interrupt();
 
            Thread.sleep(5);
        }
        catch (InterruptedException e) {
            System.out.println("Caught:" + e);
        }
        System.out.println("Exiting the main Thread");
    }
}


输出:
New thread: Thread[First  thread, 5, main]
New thread: Thread[Second thread, 5, main]
First  thread: 0
Second thread: 0
First  thread: 1
Second thread: 1
First  thread: 2
Second thread: 2
First  thread: 3
Second thread: 3
First  thread: 4
Second thread: 4
First  thread: 5
Second thread Stopped.
First  thread Stopped.
Exiting the main Thread

注意:输出可能每次都不同。
通过使用标志,我们可以随时停止线程,并且可以防止不需要的运行时错误。

  • 使用 volatile 布尔标志:我们还可以使用 volatile 布尔标志来使我们的代码线程安全。 volatile 变量直接存储在主存储器中,因此线程不能在本地缓存它的值。当多个线程访问同一个变量并且一个线程所做的更改可能对其他线程不可见时,可能会出现这种情况。在这种情况下,我们可以使用 volatile 布尔标志。
    让我们考虑下面我们使用非易失性布尔标志的代码:

Java

// Java program to illustrate non-volatile boolean flag
 
public class Main {
 
    // static used here
    // because a non-static variable
    // cannot be referenced
    // from a static context
 
    // exit variable to stop both
    // the main and inside threads
    static boolean exit = false;
 
    public static void main(String[] args)
    {
        System.out.println("started main thread..");
 
        // a thread inside main thread
        new Thread() {
            public void run()
            {
                System.out.println("started inside thread..");
 
                // inside thread caches the value of exit,
                // so changes made to exit are not visible here
                while (!exit) // will run infinitely
                {
                }
 
                // this will not be printed.
                System.out.println("exiting inside thread..");
            }
        }.start();
 
        try {
            Thread.sleep(500);
        }
        catch (InterruptedException e) {
            System.out.println("Caught :" + e);
        }
 
        // so that we can stop the threads
        exit = true;
        System.out.println("exiting main thread..");
    }
}

运行时错误:

Time Limit Exceeded

输出:

started main thread..
started inside thread..
exiting main thread..

注意:上面的代码会进入一个无限循环,并且会给出运行时错误。
上面的输出表明内部线程从未停止过。发生这种情况是因为对主线程中的“退出”变量所做的更改对内部线程不可见。之所以如此,是因为内部线程在本地缓存了 exit 的值。为了防止这种情况发生,我们可以使用 volatile 变量。下面的代码说明了这一点。

Java

// Java program to illustrate volatile boolean flag
 
public class Main {
 
    // static used here because
    // a non-static variable cannot be referenced
    // from a static context
 
    // exit variable to stop both
    // the main and inside threads
    static volatile boolean exit = false;
    public static void main(String[] args)
    {
 
        System.out.println("started main thread..");
 
        // a thread inside main thread
        new Thread() {
            public void run()
            {
 
                // changes made to exit
                // in main thread are visible here
                System.out.println("started inside thread..");
 
                // will not run infinitely
                while (!exit) {
                }
 
                // this will be printed
                System.out.println("exiting inside thread..");
            }
        }.start();
 
        try {
            Thread.sleep(500);
        }
        catch (InterruptedException e) {
            System.out.println("Caught :" + e);
        }
 
        // so that we can stop the threads
        exit = true;
        System.out.println("exiting main thread..");
    }
}
输出:
started main thread..
started inside thread..
exiting main thread..
exiting inside thread..

上面的输出表明,当我们使用 volatile 布尔标志时,我们不会陷入无限循环。这是因为 volatile 变量直接存储在主存中。换句话说,一个线程所做的更改对其他线程是可见的。因此,使用 volatile 使我们的代码成为线程安全的。

  • 使用 Thread.interrupt() 方法:每当一个中断被发送到一个线程时,它应该停止它正在执行的任何任务。很有可能每当线程接收到中断时,它就会被终止。此操作可以通过使用 interrupt() 方法来完成。每当调用 Thread.interrupt() 时,它都会将一个称为中断状态的标志设置为真。这意味着线程必须停止执行进一步的执行。此标志的默认值为 false。

Java

// Java program to illustrate
// stopping a thread
// using the interrupt() method
 
class MyThread implements Runnable {
 
    Thread t;
 
    MyThread()
    {
        t = new Thread(this);
        System.out.println("New thread: " + t);
        t.start(); // Starting the thread
    }
 
    // execution of thread starts from run() method
    public void run()
    {
        while (!Thread.interrupted()) {
            System.out.println("Thread is running");
        }
        System.out.println("Thread has stopped.");
    }
}
 
// Main class
public class Main {
    public static void main(String args[])
    {
        // creating objects t1 of MyThread
        MyThread t1 = new MyThread();
 
        try {
            Thread.sleep(1);
 
            // t1 is an object of MyThread
            // which has an object t
            // which is of type Thread
            t1.t.interrupt();
 
            Thread.sleep(5);
        }
        catch (InterruptedException e) {
            System.out.println("Caught:" + e);
        }
        System.out.println("Exiting the main Thread");
    }
}
输出:
New thread: Thread[Thread-0, 5, main]
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread is running
Thread has stopped.
Exiting the main Thread

注意:输出可能每次都不同。