Java守护线程概述

转载自  Java守护线程概述

Java的线程分为两种:User Thread(用户线程)、DaemonThread(守护线程)。

只要当前JVM实例中尚存任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束是,守护线程随着JVM一同结束工作,Daemon作用是为其他线程提供便利服务,守护线程最典型的应用就是GC(垃圾回收器),他就是一个很称职的守护者。

User和Daemon两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下Daemon Thread存在了,虚拟机也就退出了。 因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。

首先看一个例子,主线程中建立一个守护线程,当主线程结束时,守护线程也跟着结束。

package com.daemon;  import java.util.concurrent.TimeUnit;  public class DaemonThreadTest  
{  public static void main(String[] args)  {  Thread mainThread = new Thread(new Runnable(){  @Override  public void run()  {  Thread childThread = new Thread(new ClildThread());  childThread.setDaemon(true);  childThread.start();  System.out.println("I'm main thread...");  }  });  mainThread.start();  }  
}  class ClildThread implements Runnable  
{  @Override  public void run()  {  while(true)  {  System.out.println("I'm child thread..");  try  {  TimeUnit.MILLISECONDS.sleep(1000);  }  catch (InterruptedException e)  {  e.printStackTrace();  }  }  }  
}  

运行结果:

I'm child thread..  

I'm main thread...  

如果不何止childThread为守护线程,当主线程结束时,childThread还在继续运行,如下:

package com.daemon;  import java.util.concurrent.TimeUnit;  public class DaemonThreadTest  
{  public static void main(String[] args)  {  Thread mainThread = new Thread(new Runnable(){  @Override  public void run()  {  Thread childThread = new Thread(new ClildThread());  childThread.setDaemon(false);  childThread.start();  System.out.println("I'm main thread...");  }  });  mainThread.start();  }  
}  class ClildThread implements Runnable  
{  @Override  public void run()  {  while(true)  {  System.out.println("I'm child thread..");  try  {  TimeUnit.MILLISECONDS.sleep(1000);  }  catch (InterruptedException e)  {  e.printStackTrace();  }  }  }  
}  

运行结果:

I'm main thread...  
I'm child thread..  
I'm child thread..  
I'm child thread..  
I'm child thread..  

I'm child thread..(无限输出)  

可以看到,当主线程结束时,childThread是非守护线程,就会无限的执行。

守护线程有一个应用场景,就是当主线程结束时,结束其余的子线程(守护线程)自动关闭,就免去了还要继续关闭子线程的麻烦。不过博主推荐,如果真有这种场景,还是用中断的方式实现比较合理。

还有补充一点,不是说当子线程是守护线程,主线程结束,子线程就跟着结束,这里的前提条件是:当前jvm应用实例中没有用户线程继续执行,如果有其他用户线程继续执行,那么后台线程不会中断,如下:

package com.daemon;  import java.util.concurrent.TimeUnit;  public class DaemonThreadTest  
{  public static void main(String[] args)  {  Thread mainThread = new Thread(new Runnable(){  @Override  public void run()  {  Thread childThread = new Thread(new ClildThread());  childThread.setDaemon(true);  childThread.start();  System.out.println("I'm main thread...");  }  });  mainThread.start();  Thread otherThread = new Thread(new Runnable(){  @Override  public void run()  {  while(true)  {  System.out.println("I'm other user thread...");  try  {  TimeUnit.MILLISECONDS.sleep(1000);  }  catch (InterruptedException e)  {  e.printStackTrace();  }  }  }  });  otherThread.start();  }  
}  class ClildThread implements Runnable  
{  @Override  public void run()  {  while(true)  {  System.out.println("I'm child thread..");  try  {  TimeUnit.MILLISECONDS.sleep(1000);  }  catch (InterruptedException e)  {  e.printStackTrace();  }  }  }  
}  

运行结果:

I'm other user thread...  
I'm child thread..  
I'm main thread...  
I'm other user thread...  
I'm child thread..  
I'm other user thread...  
I'm child thread..  
I'm child thread..  
I'm other user thread...  
I'm other user thread...  
I'm child thread..  
I'm child thread..  
I'm other user thread...  
I'm other user thread...  
I'm child thread..  
I'm other user thread...  
I'm child thread..  
I'm other user thread...  
I'm child thread..  
I'm other user thread...  
I'm child thread..  
I'm other user thread...  
I'm child thread..  
I'm other user thread...  
I'm child thread..  
I'm other user thread...  

I'm child thread..(无限输出)  

如果需要在主线程结束时,将子线程结束掉,可以采用如下的中断方式:

package com.self;  import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.TimeUnit;  public class ThreadTest  
{  public static void main(String[] args)  {  Thread mainThread = new Thread(new Runnable(){  public void run()  {  System.out.println("主线程开始...");  Thread sonThread = new Thread(new Thread1(Thread.currentThread()));  sonThread.setDaemon(false);  sonThread.start();  try  {  TimeUnit.MILLISECONDS.sleep(10000);  }  catch (InterruptedException e)  {  e.printStackTrace();  }  System.out.println("主线程结束");  }  });  mainThread.start();  }  }  class Thread1 implements Runnable  
{  private Thread mainThread;  public Thread1(Thread mainThread)  {  this.mainThread = mainThread;  }  @Override  public void run()  {  while(mainThread.isAlive())  {  System.out.println("子线程运行中....");  try  {  TimeUnit.MILLISECONDS.sleep(1000);  }  catch (InterruptedException e)  {  e.printStackTrace();  }  }  }  }  

运行结果:

主线程开始...  

子线程运行中....  
子线程运行中....  
子线程运行中....  
子线程运行中....  
子线程运行中....  
子线程运行中....  
子线程运行中....  
子线程运行中....  
子线程运行中....  
子线程运行中....  
子线程运行中....  
主线程结束  

回归正题,这里有几点需要注意:
(1) thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。
(2) 在Daemon线程中产生的新线程也是Daemon的。 
(3) 不要认为所有的应用都可以分配给Daemon来进行服务,比如读写操作或者计算逻辑。

写java多线程程序时,一般比较喜欢用java自带的多线程框架,比如ExecutorService,但是java的线程池会将守护线程转换为用户线程,所以如果要使用后台线程就不能用java的线程池。

如下,线程池中将daemon线程转换为用户线程的程序片段:

static class DefaultThreadFactory implements ThreadFactory {  private static final AtomicInteger poolNumber = new AtomicInteger(1);  private final ThreadGroup group;  private final AtomicInteger threadNumber = new AtomicInteger(1);  private final String namePrefix;  DefaultThreadFactory() {  SecurityManager s = System.getSecurityManager();  group = (s != null) ? s.getThreadGroup() :  Thread.currentThread().getThreadGroup();  namePrefix = "pool-" +  poolNumber.getAndIncrement() +  "-thread-";  }  public Thread newThread(Runnable r) {  Thread t = new Thread(group, r,  namePrefix + threadNumber.getAndIncrement(),  0);  if (t.isDaemon())  t.setDaemon(false);  if (t.getPriority() != Thread.NORM_PRIORITY)  t.setPriority(Thread.NORM_PRIORITY);  return t;  }  
}  
注意到,这里不仅会将守护线程转变为用户线程,而且会把优先级转变为Thread.NORM_PRIORITY。

如下所示,将守护线程采用线程池的方式开启:

package com.daemon;  import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.TimeUnit;  public class DaemonThreadTest  
{  public static void main(String[] args)  {  Thread mainThread = new Thread(new Runnable(){  @Override  public void run()  {  ExecutorService exec = Executors.newCachedThreadPool();  Thread childThread = new Thread(new ClildThread());  childThread.setDaemon(true);  exec.execute(childThread);  exec.shutdown();  System.out.println("I'm main thread...");  }  });  mainThread.start();  }  
}  class ClildThread implements Runnable  
{  @Override  public void run()  {  while(true)  {  System.out.println("I'm child thread..");  try  {  TimeUnit.MILLISECONDS.sleep(1000);  }  catch (InterruptedException e)  {  e.printStackTrace();  }  }  }  
}  

运行结果:

I'm main thread...  
I'm child thread..  
I'm child thread..  
I'm child thread..  
I'm child thread..  
I'm child thread..  
I'm child thread..  
I'm child thread..  
I'm child thread..  

I'm child thread..(无限输出)  

 上面代码证实了线程池会将守护线程转变为用户线程。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329124.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php while循环次数,php while循环得到循环次数

php while循环得到循环次数复制代码 代码如下:$link mysql_connect(localhost,root,pwd);mysql_select_db(db);$sql "select region_id,local_name from regions where region_grade1";$result mysql_query($sql);$i 0;while ($row mysql_fetch_assoc($result)) {…

EntityFramework和EntityFramework.Extended使用说明——性能,语法和产生的sql

环境说明:EntityFramework 6.1.3和.Net Framework4.5性能注意事项:https://msdn.microsoft.com/zh-cn/library/cc853327.aspx比较精髓的一点:查询执行的各个阶段中的准备查询,每个唯一查询一次。包括编写查询命令、基于模型和映射元数据生成命令树和定义所返回数据的形状的成本…

三个水桶(看了三遍,想了五遍!)

转载至:微信公众号: 创业励志网 一 有位木匠砍了一树,把它做了三个木桶。 一个装粪,就叫粪桶,众人躲着; 一个装水,就叫水桶,众人用着; 一个装酒,就叫酒桶&…

nginx解析php失败,为什么nginx不能解析php?

只运行过这些代码yum install -y vim wget zip unzip git httpd php php-mysql php-odbc php-ldap php-gd php-mbstring php-xml php-xml-rpc php-bcmath libjpeg* mariadb ;rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarc…

.NET Core amp; ASP.NET Core 1.0在Redhat峰会上正式发布

众所周知,Red Hat和微软正在努力使.NET Core成为Red Hat企业版Linux (RHEL)系统上的一流开发平台选项。这个团队已经一起工作好几个月了,RHEL对.NET有许多需求。今天在RedHat 峰会DevNation 上宣布了.NET Core & ASP.NET Core 1.0 RTM。Red Hat有一个新的关于在…

任务调度(三)——Timer的替代品ScheduledExecutorService简介

转载自 任务调度(三)——Timer的替代品ScheduledExecutorService简介先前的两篇博文《任务调度(一)——jdk自带的Timer》和《任务调度(二)——jdk自带的Timer 动态修改任务执行计划》中,简单介绍了一下Timer,可以实现几本的功能,但是在多线程…

jquery实现动态五角星评分

先上代码&#xff0c;最后附属上我的实现思路&#xff0c;新手做的bug多&#xff0c;大牛勿喷&#xff1a;请看代码&#xff1a; ☆☆☆☆☆<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-trans…

php中时间轴,PHP时间轴函数

26 04 2013PHP时间轴函数Yinchiang | 0我们会经常看见现在许多网站的留言或者评论的时间变得十分有趣&#xff0c;刚刚、3分钟前、1天前等等人性化的时间轴好吧&#xff0c;我承认这个函数是转载的&#xff0c;部分按照自己的需求修改了一点点。/*** 时间轴函数&#xff0c;单位…

开源Asp.Net Core小型社区系统

前言 盼星星盼月亮&#xff0c;Asp.Net Core终于发布啦&#xff01;&#xff01; Asp.Net发布时我还在上初中&#xff0c;没有赶上。但是Asp.Net Core我从beta版本便一直关注。最初项目名叫Asp.Net VNext&#xff0c;然后改名叫Asp.Net 5。最煎熬的是RC1发布后&#xff0c;官方…

Java多线程干货系列(1):Java多线程基础

转载自 Java多线程干货系列&#xff08;1&#xff09;&#xff1a;Java多线程基础前言 多线程并发编程是Java编程中重要的一块内容&#xff0c;也是面试重点覆盖区域&#xff0c;所以学好多线程并发编程对我们来说极其重要&#xff0c;下面跟我一起开启本次的学习之旅吧。 正文…

php accesscontrolalloworigin,设置Access-Control-Allow-Origin实现跨域访问

这篇文章主要介绍了Ajax 设置Access-Control-Allow-Origin实现跨域访问,非常不错&#xff0c;具有参考借鉴价值&#xff0c;需要的朋友可以参考下ajax跨域访问是一个老问题了&#xff0c;解决方法很多&#xff0c;比较常用的是JSONP方法&#xff0c;JSONP方法是一种非官方方法&…

.NET Core:面向未来的开源跨平台开发技术

作为一种全新的开源和跨平台的开发平台&#xff0c;.NET Core 历经两年多的开发&#xff0c;终于在于2016年6月27日针对所有主流服务器和桌面操作系统发布 1.0 RTM 版本。.NET Core 是一种通用开发平台&#xff0c;它包含了自动内存管理和现代化高级开发语言等重要特性&#xf…

Sublime Text 3 快捷键总结(拿走)

以下是个人总结不完全的快捷键总汇&#xff0c;祝愿各位顺利解放自己的鼠标。选择类CtrlD 选中光标所占的文本&#xff0c;继续操作则会选中下一个相同的文本。AltF3 选中文本按下快捷键&#xff0c;即可一次性选择全部的相同文本进行同时编辑。举个栗子&#xff1a;快速选中并…

Java多线程学习

转载自 Java多线程学习本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。在这之前&#xff0c;首先让我们来了解下在操作系统中进程和线程的区别&#xff1a;进程&#xff1a;每个进程都有独立的代码和数据空间&#…

php面试心得,php面试题的总结

这篇文章介绍的内容是关于php面试题的总结&#xff0c;有着一定的参考价值&#xff0c;现在分享给大家&#xff0c;有需要的朋友可以参考一下1. 什么事面向对象&#xff1f;主要特征是什么&#xff1f;面向对象是程序的一种设计方式&#xff0c;它利于提高程序的重用性&#xf…

展望C# 7

译者&#xff1a;雪落无痕 xdj 目前的 C# 编译器&#xff08;即 Roslyn&#xff09;于 2014 年 4 月开源。目前不仅是编译器在 GitHub 上开发&#xff1b;语言的设计也是进行公开的讨论。 这允许感兴趣的各方了解语言下一个版本的样子。这篇文章概述了当前在设计语言新特性时的…

Java 线程池详解及实例代码

转载自 Java 线程池详解及实例代码这篇文章主要介绍了Java 线程池的相关资料,并符实例代码&#xff0c;帮助大家学习参考&#xff0c;需要的朋友可以参考下线程池的技术背景 在面向对象编程中&#xff0c;创建和销毁对象是很费时间的&#xff0c;因为创建一个对象要获取内存资…

jQuery最简单的留言功能^-^

先上代码&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml" xml:lang"en"> <h…

rocketmq java home,rocketmq 安装与配置以及遇到的问题

不废话&#xff0c;搞起双M 模式环境1&#xff0c;java-1.8这里有个问题&#xff0c;centos 安装yum install java-1.8 是只是安装的java 运行环境jre&#xff0c;还缺少开发包所以在编译的时候会有问题&#xff0c;使用yum install yum install java-1.8.0-openjdk-devel* 这…

聊聊并发(八)——Fork/Join框架介绍

转载自 聊聊并发&#xff08;八&#xff09;——Fork/Join框架介绍1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架&#xff0c; 是一个把大任务分割成若干个小任务&#xff0c;最终汇总每个小任务结果后得到大任务结果的框架。 我们再通过F…