万隆的笔记 万隆的笔记
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
  • JUC介绍
  • 并发编程核心概念与主要内容
  • Java线程创建与使用
  • 线程生命周期
  • synchronized关键字
  • wait与notify
  • 线程中断-interrupt
  • 线程优雅关闭
    • stop与destory
    • 设置守护线程
    • 设置关闭的标志位
  • JMM内存模型
  • volatile关键字
  • final关键字
  • Lock
  • JUC并发编程
2022-05-06
目录

线程优雅关闭

# 线程优雅关闭

如何关闭一个线程?主要有以下方法

  • stop与destory函数(不推荐)
  • 设置为守护线程
  • 设置关闭的标志位

# stop与destory

线程是“一段运行中的代码”,一个运行中的方法。运行到一半的线程不推荐强制杀死。

在Java中,有stop()、destory()等方法,但这些方法官方明确不建议使用。原因很简单,如果强制杀死线程,则线程中所使用的资源,例如文件描述符、网络连接等无法正常关闭。因此,一个线程一旦运行起来,不要强行关闭,合理的做法是让其运行完(也就是方法执行完毕),干净地释放掉所有资源,然后退出。如果是一个不断循环运行的线程,就需要用到线程间的通信机制,让主线程通知其退出。

# 设置守护线程

daemon线程和非daemon线程的对比:

public class Main {
    public static void main(String[] args) {
        MyDaemonThread myDaemonThread = new MyDaemonThread();
        // 将当前线程设置为daemon线程:守护线程
        myDaemonThread.setDaemon(true);
        myDaemonThread.start();
        // 启动非daemon线程,当非daemon线程结束,不管daemon线程是否结束,都结束JVM进程。
        MyThread myThread = new MyThread();
        myThread.start();
    }
}


class MyDaemonThread extends Thread {

    @Override
    public void run() {
        while (true) {
            System.out.println("daemon线程。。。");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class MyThread extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("非daemon线程");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

对于上面的程序,在thread.start()前面加一行代码thread.setDaemon(true)。当main(...)函数退出后,线程thread就会退出,整个进程也会退出。

当在一个JVM进程里面开多个线程时,这些线程被分成两类:守护线程和非守护线程,默认都是非守护线程。Java规定当所有的非守护线程退出后,整个JVM进程就会退出。意思就是守护线程不影响整个 JVM 进程的退出。例如,垃圾回收线程就是守护线程,它们在后台默默工作,当开发者的所有前台线程(非守护线程)都退出之后,整个JVM进程就退出了。

# 设置关闭的标志位

开发中一般通过设置标志位(一个变量标识状态)的方式,停止循环运行的线程。

public class MyThread extends Thread {

    private boolean flag = true;

    @Override
    public void run() {
        while (flag) {
            System.out.println("线程正在运行。。。");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // 用于关闭线程
    public void stopRunning() {
        this.flag = false;
    }

    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        myThread.start();
        Thread.sleep(3000);
        // 置标志位,停止
        myThread.stopRunning();
        myThread.join();
        System.out.println("main线程退出");
    }

}

但上面的代码有一个问题:如果MyThread在while循环中阻塞在某个地方,例如里面调用了object.wait()函数,那它可能永远没有机会再执行 while(flag)代码,也就一直无法退出循环。此时,就要用到InterruptedException()与interrupt()函数。

上次更新: 5/30/2023, 12:05:21 AM
JMM内存模型

JMM内存模型→

最近更新
01
2025
01-15
02
Elasticsearch面试题
07-17
03
Elasticsearch进阶
07-16
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式