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的资源,对吧?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值