先来看个例子:
首先我们知道线程的几个状态,从new Thread 开始为New状态,当调用start()方法后,变为runnable状态,接下来有可能变为:Running | Terminated | Blocked 状态。
以上代码线程状态:
- new Thread 开始为 New 状态
- 调用start()方法后为 Runnable 状态。
- 执行System.out.println(Thread.currentThread().getName()+" running");后为: Running 状态。
- 执行Thread.sleep(10000);后为:Blocked 状态。
- 执行完后 Terminated 状态。
以上为Thread t 线程,main线程呢?
- 执行public static void main(String[] args) 后 Running 状态。
- 执行Thread.sleep(10_000);后为:Blocked 状态。
- 执行System.out.println(Thread.currentThread().getName()); 后 Terminated 状态。
- 执行public static void main(String[] args) 后 Running 状态。
问题:两个线程皆结束为什么JVM没有退出呢?
运行结果:
main线程这个时候是已经结束了的,从JConsole工具可以看出:
application 没有退的原因是因为还有一些active的线程。
JVM怎么知道这些active的线程呢?
- 因为放到了同一个ThreadGroup里面,也是通过ThreadGroup去管理的,它看到了active线程还是有活跃的
加多个属性把thread t 设置为守护线程
t.setDaemon(true);
当main线程生命周期结束之后,创建的守护线程也就跟着结束!
运行结果:
不管thread t 是否Running结束都把线程干掉。
这东西的用处:
- 建立网络连接
- A(client)<--------------------------->B(server)
- 从A到B建立长连接,每隔3秒发送一次心跳包。
- A不断的向B发送心跳包,B返回心跳相应,证明这个连接是可用的,如果不可用重新连接。
- 一旦当前的线程创建好了一个线程之后,要维护这个心跳,这个心跳和业务没有关系,和这个连接要拿去发送报文或通信也没有多大关系,就是做维护的一些事情。
- 这时,在创建连接之后的线程开辟一个daemonThread(health check)做心跳检查。
- 好处:
- 假设没有做成daemonThread,当建立连接的这个线程可能已经死了,但是你的哪个线程它不会死,必须你通知他或者手动关掉,关闭时可能还关不了,因为标记为不可用了。
- 也就是说所有的业务线程都已经死掉了,但是应用程序关不了。(进程一直还在,因为还有活动线程在运行,JVM不会退出,但是又没有做什么事情,可能在通信的过程中不断的报错,但你不知道)。
- 如果设置为守护线程那就很容易得到解决。(
守护线程可以帮你做一些辅助性的东西
)。
- 建立网络连接
问题:在Thread里面创建daemonThread t,启动后main线程结束,t随之结束,那么在t里面再创建一个线程L把他设置为daemonThread,t结束后他会退出吗?
问题:如果把L设置为非守护线程,mian和t运行结束之后,JVM能退出吗?