java 守护线程 作用_java中守护线程的一些概念和用法
网上的资料中,守护线程的功能一般都是“只要当前JVM实例中尚存任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束是,守护线程随着JVM一同结束工作,Daemon作用是为其他线程提供便利服务,守护线程最典型的应用就是GC(垃圾回收器),他就是一个很称职的守护者。”
可是,我发现真实情况却不是描述的这么回事,因为我对java也不懂,所以在此记录一下守护线程中的一些问题。
我的思路是:
在main线程中建立两个线程,一个线程A只打印一行信息就退出,它被设置成守护线程,另一个线程B通过sleep和循环来进行时间控制,让它多运行一会,他被设置成非守护线程。如果按照上面的说明,我认为线程A怎么说也要和线程B的消亡时间是一样的。实际情况却不是这样的。
下面是代码:
文件 ThreadDaemon.java
packagejavaStudy.threadStudy;importjava.util.Date;public classThreadDaemon {public static voidmain(String[] args) {//Thread.currentThread().setDaemon(true);//Thread.currentThread().start();//系统的main函数使用一个主线程,主线程不是守护线程,也不能被设置成守护线程
System.out.println(Thread.currentThread().getName() + "\tprocess begin\t" + (new Date()) + "\t"
+ Thread.currentThread().isDaemon() + "\tthread amount\t"
+Thread.currentThread().getThreadGroup().activeCount());
showThreadName();//新建一个线程,并将其设置成守护线程,他的操作仅仅是打印一行信息。
Thread t = newThread(ThreadDaemon::daemonPrint);
t.setDaemon(true);
t.start();
System.out.println(Thread.currentThread().getName()+ "\tafter create thread A\t" + (new Date()) + "\t"
+ Thread.currentThread().isDaemon() + "\tthread amount\t"
+Thread.currentThread().getThreadGroup().activeCount());
showThreadName();//再建立一个线程,将其设置成用户线程,即非守护线程。让他多执行一会。
try{
Thread.sleep(1000 * 3);
Thread thread2= newThread(ThreadDaemon::print);
thread2.setDaemon(false);
thread2.start();
System.out.println(Thread.currentThread().getName()+ "\tafter create thread B\t" + (new Date()) + "\t"
+ Thread.currentThread().isDaemon() + "\tthread amount\t"
+Thread.currentThread().getThreadGroup().activeCount());
showThreadName();
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ "\tExit:" + "\t" + (new Date()) + "\t"
+ Thread.currentThread().isDaemon() + "\tthread amount "
+Thread.currentThread().getThreadGroup().activeCount());
showThreadName();//System.exit(0) 是退出jvm。如果有此代码,则子线程也会直接随着主线程而退出。如果没有此代码,jvm会在子线程结束的时候而退出。//System.exit(0);
}//用户线程的调用
public static voidprint() {int counter = 1;while (counter < 5) {try{
Thread.sleep(3 * 1000); //sleep for 10 seconds
System.out.println(Thread.currentThread().getName() + "\tbefore Counter:" + counter++ + "\t"
+ (new Date()) + "\t" + Thread.currentThread().isDaemon() + "\tthread amount "
+Thread.currentThread().getThreadGroup().activeCount());
Thread.sleep(3 * 1000); //sleep for 10 seconds
System.out.println(Thread.currentThread().getName() + "\tafter Counter:" + counter++ + "\t"
+ (new Date()) + "\t" + Thread.currentThread().isDaemon() + "\tthread amount "
+Thread.currentThread().getThreadGroup().activeCount());
showThreadName();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}//守护线程的调用
public static voiddaemonPrint() {try{
Thread.sleep(6 * 1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
Thread.currentThread().getName()+ "\t" + (new Date()) + "\t" +Thread.currentThread().isDaemon()+ "\tthread amount " +Thread.currentThread().getThreadGroup().activeCount());
showThreadName();
}//显示线程名称
public static voidshowThreadName() {
ThreadGroup currentGroup=Thread.currentThread().getThreadGroup();int noThreads =currentGroup.activeCount();
Thread[] lstThreads= newThread[noThreads];
currentGroup.enumerate(lstThreads);for (int i = 0; i < noThreads; i++) {
System.out.println("==============="+lstThreads[i].getName() + "\t" +lstThreads[i].isDaemon());
}
}
}
以上代码,我根据程序休眠的时间,让主线程先退出,然后发现守护线程却在第二个退出的。因为他不是死循环,所以提前退出了?这么说来,如果一个线程要想是守护线程的话,他必须是死循环?也就是说,从程序表面看,守护线程一定要比用户线程存活的久一点?这么说来,将一个理论上活的更久的线程,设置成守护线程,仅仅是让它自动和用户线程一起消亡罢了。实际上,通过延长上面代码的daemonPrint()的sleep的时间,也可以验证守护线程会和用户线程一起消亡。
下面是程序的日志:
main process begin Tue Oct 16 17:17:29 CST 2018 false thread amount 1
===============mainfalse
mainafter create thread ATue Oct 16 17:17:30 CST 2018falsethread amount2
===============mainfalse
===============Thread-0true
mainafter create thread BTue Oct 16 17:17:33 CST 2018falsethread amount3
===============mainfalse
===============Thread-0true
===============Thread-1false
mainExit:Tue Oct 16 17:17:33 CST 2018falsethread amount 3
===============mainfalse
===============Thread-0true
===============Thread-1false
Thread-0Tue Oct 16 17:17:36 CST 2018truethread amount 3
===============Thread-0true// 这一行日志,说明他是守护线程,但是下面却没有了他的名字。因为他不是死循环,所以提前退出了?
===============Thread-1false
===============DestroyJavaVMfalse
Thread-1before Counter:1Tue Oct 16 17:17:36 CST 2018falsethread amount 2
Thread-1after Counter:2Tue Oct 16 17:17:39 CST 2018falsethread amount 2
===============Thread-1false
===============DestroyJavaVMfalse
Thread-1before Counter:3Tue Oct 16 17:17:42 CST 2018falsethread amount 2
Thread-1after Counter:4Tue Oct 16 17:17:45 CST 2018falsethread amount 2
===============Thread-1false
===============DestroyJavaVMfalse
结论:代码的逻辑让守护线程提前于用户线程消亡的情况下,守护线程并不会主动延长生命和用户线程一起消亡。但是,代码的逻辑让守护线程延迟于用户线程消亡的情况下,守护线程会提前和用户线程一起消亡。这样也可以理解,毕竟CPU资源那么金贵,既然守护线程提前与用户线程消亡,那他没有必要赖着占用CPU的资源,对吧?
java 守护线程 作用_java中守护线程的一些概念和用法相关推荐
- java多线程 线程安全_Java中的线程安全
java多线程 线程安全 Thread Safety in Java is a very important topic. Java provides multi-threaded environme ...
- java 全局变量线程安全_Java中的线程安全全局变量
我试图了解 java中的线程安全机制,我需要一些帮助.我上课了: public class ThreadSafe { private Executor executor = new Scheduled ...
- java finally的作用_java中finally关键字的特点和作用是什么
java中finally关键字的特点和作用是什么 发布时间:2020-09-08 11:12:01 来源:亿速云 阅读:114 作者:小新 小编给大家分享一下java中finally关键字的特点和作用 ...
- java 构造函数的作用_Java中构造函数的作用(转)
https://blog.csdn.net/vipmao/article/details/51530954,我觉得讲的非常好,学习到了 构造函数的最大作用就是创建对象时完成初始化,当我们在new一个对 ...
- java里面序列化作用_java中序列化的作用
一 什么叫序列化 通俗点讲:它是处理对象流的一种机制,即可以很方便的保存内存中java对象的状态,同时也为了方便传输. 二 序列化有什么作用 1.方便传输,速度快,还很安全,被调用方序列化,调用方反 ...
- java throws的作用_Java中throws..throw的使用与说明
throws语句 throws总是出现在一个函数头中,用来标明该成员函数可能抛出的各种异常.对大多数Exception子类来说,Java 编译器会强迫你声明在一个成员函数中抛出的异常的类型.如果异常的 ...
- java comparable接口作用_Java 中 Comparable 接口的意义和用法
一, 为何需要实现Comparable接口 我们知道Collections类中包含很多对实现Collection接口的容器各种操作的静态方法. 当然, 其中最长用的莫过于排序了(Collections ...
- java的rsa作用_java 中RSA的方式实现非对称加密的实例
java 中rsa的方式实现非对称加密的实例 rsa通俗理解: 你只要去想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密:同理,既然是签名,那肯 ...
- java new string作用_java中直接new String对象?
首先明确一点,在Java中==比较的是两个对象的地址,equals()比较的是两个对象的值,如果使用equals()来替换==,则两个输出结果都为true. 言归正传,为什么第一个返回为false? ...
最新文章
- 【神经网络】(13) ShuffleNetV2 代码复现,网络解析,附Tensorflow完整代码
- Cinder LVM Oversubscription in thin provisioning
- 前端学习(2774):方式1进行路由跳转
- Keras:Transfer learning
- python epoll 写数据到数据库_Python--day40(EPOLL的使用、数据库基础)
- 该伙伴事务管理器已经禁止了它对远程/网络事务的支持
- STL-vector容器
- 我的日程安排表(2022-6-6)(内含I、II、III的解法)
- Jenkins--下载安装及简单配置
- KB和kB,MB和mb,详细解释计算机存储单位
- ES6 入门:let
- 【分布式】关于分布式“一致性”的讨论
- 页面中播放fla文件
- 级联(cascade)
- 电脑中常用的“扇区”、“簇”、“块”、“页”等概念
- 【STM32学习】(19)STM32实现直流电机测转速(霍尔传感器)
- SCRM系统助力企业精细化管理会员 再造会员营销
- 完整优雅的卸载腾讯云云服务器安全监控组件
- 表单验证(验证手机号是否存在,验证码倒计时)
- 备战Noip2018模拟赛10(B组) T1 Max 和最大
热门文章
- String StringBuilder StringBuffer
- 2018牛客网暑假ACM多校训练赛(第六场)I Team Rocket 线段树
- SQL数据查询之——单表查询
- flash事件冒泡的理解
- 人性歪曲的心理调适 一【浮躁心理、偏激心理、自卑心理、自杀心理、愤怒心理】...
- .NET+Oracle 9i时产生的未在本地计算机上注册“OraOLEDB.Oracle.1”提供程序
- STM32F103/429串口IAP+Ymodem升级
- 马斯克、吴恩达等27人出镜:AI可能成为不朽独裁者,人类就像蚂蚁束手就擒
- 【附】Python安装
- android 扫描SDCard.