Java用户线程和守护线程
今天看Java一个关于多线程返回值方式的示例,发现一个自己不太能理解的问题,就是在主线程中启动了几个工作线程,主线程中也没有join,工作线程居然也是正常输出了回调的结果。这个跟linux C++下的线程知识可是不一样的,在C++下,如果main函数退出了,那么所有的子线程也就退出了,我一开始怀疑是不是书上写的不够仔细,没有测试,所以自己写了几个类简单的测试了一下。代码如下:
ThreadCallback.java代码:
package thread.callback;
public class ThreadCallback {
public void callBack(String msg) {
System.out.println(msg);
}
}
WorkThread.java代码:
package thread.callback;
public class WorkThread extends Thread{
private ThreadCallback callback;
private String threadName;
public WorkThread(ThreadCallback _callback, String _threadName) {
// TODO Auto-generated constructor stub
this.callback = _callback;
this.threadName = _threadName;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.callback.callBack(this.threadName);
}
}
test.java代码:
package thread.callback;
public class test {
public static void main(String[] args) {
for (int i=0; i<5; ++i) {
ThreadCallback callback = new ThreadCallback();
WorkThread workThread = new WorkThread(callback, "thread" + Integer.toString(i));
workThread.start();
}
System.out.println("to be end");
}
}
代码非常简单啊,就是WorkThread中简单回调Callback中的接口,然后再callback中打印一下,运行的结果如下:
to be end
thread0
thread2
thread3
thread1
thread4
从输出结果(thread输出顺序,每次不一定一样)可以看出来,主线程退出之后,其创建的几个子线程还是在正常运行的,直到输出了指定的结果。那么也就是跟之前linux C++下的主从线程关系不太一样了。经过搜索,发现Java线程有一个是否为守护线程的属性,默认情况下这个属性是不设置的,为false,代表这个线程是一个用户线程,如果使用Thread的setDaemon接口设置一下,那么线程属性就会变成守护线程。
用户线程不会随着主线程退出而结束,而是会继续在JVM中运行的,直到自身结束,JVM也会等所有用户线程都执行完毕才退出。
而守护线程会在所有用户线程(包括主线程)退出之后,一起退出,这时候JVM也就退出了。
我们把test.java改成这样:
package thread.callback;
public class test {
public static void main(String[] args) {
for (int i=0; i<5; ++i) {
ThreadCallback callback = new ThreadCallback();
WorkThread workThread = new WorkThread(callback, "thread" + Integer.toString(i));
workThread.setDaemon(true);
workThread.start();
}
System.out.println("to be end");
}
}
新增setDaemon,在thread运行之前设置,然后运行程序,程序只打印"to be end"然后就退出了。
如果我们将5个子线程中的4个设置为守护线程,一个为用户线程,会怎样呢?
test.java代码
package thread.callback;
public class test {
public static void main(String[] args) {
for (int i=0; i<5; ++i) {
ThreadCallback callback = new ThreadCallback();
WorkThread workThread = new WorkThread(callback, "thread" + Integer.toString(i));
if (i != 4)
workThread.setDaemon(true);
workThread.start();
}
System.out.println("to be end");
}
}
那么也会可能输出所有线程结果。为啥说可能呢,这要看唯一的用户线程thread4啥时候退出了,它一退出,那么其他守护进程不管有没有执行完,都会被迫退出。在我们上面的例子中比较难出现,因为thread4是最后一个启动的,而且大家都做相同简单的事情,如果把thread4改成thread1,那么就非常容易测试出来了。
比如我们把WorkThread.java的run改成这样:
public void run() {
// TODO Auto-generated method stub
try {
if (threadName.equals("thread4"))
Thread.sleep(1000);
else
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.callback.callBack(this.threadName);
}
那么输出结果就是:
to be end
thread4
可以从上面的运行结果中看出用户线程和守护线程的区别了!
Java用户线程和守护线程的更多相关文章
- 【java多线程】用户线程和守护线程的区别
java中线程分为两种类型:用户线程和守护线程.通过Thread.setDaemon(false)设置为用户线程:通过Thread.setDaemon(true)设置为守护线程.如果不设置次属性,默认 ...
- java高并发系列 - 第9天:用户线程和守护线程
守护线程是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程.JIT线程都是守护线程.与之对应的是用户线程,用户线程可以理解为是系统的工作线程,它会完成这个程序需要完成的业务操作.如果 ...
- java 用户线程和守护线程
在Java中通常有两种线程:用户线程和守护线程(也被称为服务线程)通过Thread.setDaemon(false)设置为用户线程通过Thread.setDaemon(true)设置为守护线程线程属性 ...
- java并发:初探用户线程和守护线程
用户线程和守护线程 用户线程 用户线程执行完,jvm退出.守护线程还是可以跑的 /** * A <i>thread</i> is a thread of execution i ...
- 额!Java中用户线程和守护线程区别这么大?
在 Java 语言中线程分为两类:用户线程和守护线程,而二者之间的区别却鲜有人知,所以本文磊哥带你来看二者之间的区别,以及守护线程需要注意的一些事项. 1.默认用户线程 Java 语言中无论是线程还是 ...
- Java:多线程<四> Lock、停止线程、守护线程、join、优先级&yield
Java1.5以后,Condition将Object监视器方法(wait, notify, notifyAll)分解成截然不同的对象,以便通过这些对象与任意Lock实现组合使用为每个对像提供多个等待s ...
- Java中的守护线程 & 非守护线程(简介)
Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...
- Java多线程编程之守护线程
Java的线程分为两种,一个是用户线程,一个是守护线程.守护线程守护的对象就是用户线程,当用户线程结束后,守护它的守护线程也就会结束.二者的本质基本是一样的,唯一区别在于何时结束. 用户线程:直到自己 ...
- JAVA笔记13__创建线程/线程休眠/等待线程终止/线程中断/守护线程
/** * 线程:是进程的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少有一个进程(单线程程序) * 多线程两种实现方法:1.继承Thread类 2.实现Runnable ...
随机推荐
- JS对数字进行货币格式化并且保留两位小数点,小数用0补全
/** * 将数值四舍五入(保留2位小数)后格式化成金额形式 * * @param num 数值(Number或者String) * @return 金额格式的字符串,如'1,234,567.45' ...
- Myeclipse——SSH框架搭建
Struts2.x+Spring3.x+Hibernate3.x 一.首先建立一个Web 工程 二.搭建Struts 右键工程,选择MyEclipse->Add Struts Capabilit ...
- iOS系统网络抓包方法
转到自己的博客收藏. 1. 网络共享 + 可视化抓包工具 基本原理 原理比较简单,ios设备通过代理方式共享连接mac电脑的无线网卡,使用抓包工具抓包,然后进行分析(我们推荐使用Wireshark,在 ...
- Openwrt 编译报错:rootfs image is too big解决方法
修改: tools/firmware-utils/src/mktplinkfw2.c static struct flash_layout layouts[] = { { .id = "8M ...
- Java学习之多态
多态的概念 多态==晚绑定. 不要把函数重载理解为多态. 因为多态是一种运行期的行为,不是编译期的行为. 多态:父类型的引用可以指向子类型的对象. 比如 Parent p = new Child(); ...
- GDI+ 绘制经验
现有一种场景,鼠标移动时,假设鼠标坐标为 X , Y , 需实时在 坐标 (X , 0) , (0 , Y) 两处更新内容. 方案一:增加两个label ,或其它控件,鼠标移动时,实时更新 label ...
- NOIP2016之反面教材提供
NOIP 2016信息竞赛总结 竞赛历程总结: 算下来一共学了11个月的信息竞赛,从最初进来的时候大概会一点最最基础的语法,上课什么也听不懂,然后一直追进度,我想在这个阶段中我的问题主要是自己知道自己 ...
- 7个步骤:让JavaScript变得更好
Dan Odell介绍了他编写的七步写出无瑕代码的计划,是在简化过程中最有用的工具. 随着浏览器性能提高,伴随着新的HTML5的编程接口的稳步采用,网页上的JavaScript的音量在逐渐增加.然 ...
- Man——send(2)翻译
##纯手打 Man——send(2) -->NAME: send, sendto, sendmsg - 在socket上发送一条消息 -->总览: #include <sys/typ ...
- C/C++函数调用的几种方式及函数名修饰规则以及c++为什么不允许重载仅返回类型不同的函数
我们知道,调用函数时,计算机常用栈来存放函数执行需要的参数,由于栈的空间大小是有限的,在windows下栈是向低地址扩展的数据结构,是一块连续的内存区域.这句话的意思是栈顶的地址和栈的最大容量是系统预 ...