Granda's Blog

JAVA:如何优雅地关闭一个线程

使用stop()方法关闭线程(已弃用)

  • 直接调用stop()方法关闭一个线程,可能会在线程执行的任意位置将线程给关闭,而且关闭线程时,该线程已经执行的操作和还未来得及执行的操作都是不可预测的,可能会导致数据的不完整,故这样关闭一个线程是不安全的

使用volatile标志位来关闭一个线程

  • 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    public class MyRunnable implements Runnable{
    //设置退出标志位
    private volatile boolean flag = false;
    @Override
    public void run() {
    System.out.println(Thread.currentThread().getName()+"建立");
    try {
    Thread.sleep(1000L);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    while(!flag){
    //需要保护执行的内容,线程终止不会导致在某条代码处被终止
    System.out.println(Thread.currentThread().getName()+":执行命令1");
    System.out.println(Thread.currentThread().getName()+":执行命令2");
    }
    System.out.println(Thread.currentThread().getName()+"终止");
    }
    public void setFlag(boolean flag){
    this.flag = flag;
    }
    }
    public class ThreadTest {
    public static void main(String[] args){
    MyRunnable runnable = new MyRunnable();
    //开启3个线程
    new Thread(runnable,"线程1").start();;
    new Thread(runnable,"线程2").start();;
    new Thread(runnable,"线程3").start();;
    try {
    Thread.sleep(2000L);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    //设置终止标志位,使进程终止
    runnable.setFlag(true);
    }
    }

运行结果开始

运行结果结束

  • 显然每个线程都会执行完命令2后才会被终止,这样就避免了stop()方法导致的数据不安全