今天看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用户线程和守护线程的更多相关文章

  1. 【java多线程】用户线程和守护线程的区别

    java中线程分为两种类型:用户线程和守护线程.通过Thread.setDaemon(false)设置为用户线程:通过Thread.setDaemon(true)设置为守护线程.如果不设置次属性,默认 ...

  2. java高并发系列 - 第9天:用户线程和守护线程

    守护线程是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程.JIT线程都是守护线程.与之对应的是用户线程,用户线程可以理解为是系统的工作线程,它会完成这个程序需要完成的业务操作.如果 ...

  3. java 用户线程和守护线程

    在Java中通常有两种线程:用户线程和守护线程(也被称为服务线程)通过Thread.setDaemon(false)设置为用户线程通过Thread.setDaemon(true)设置为守护线程线程属性 ...

  4. java并发:初探用户线程和守护线程

    用户线程和守护线程 用户线程 用户线程执行完,jvm退出.守护线程还是可以跑的 /** * A <i>thread</i> is a thread of execution i ...

  5. 额!Java中用户线程和守护线程区别这么大?

    在 Java 语言中线程分为两类:用户线程和守护线程,而二者之间的区别却鲜有人知,所以本文磊哥带你来看二者之间的区别,以及守护线程需要注意的一些事项. 1.默认用户线程 Java 语言中无论是线程还是 ...

  6. Java:多线程<四> Lock、停止线程、守护线程、join、优先级&yield

    Java1.5以后,Condition将Object监视器方法(wait, notify, notifyAll)分解成截然不同的对象,以便通过这些对象与任意Lock实现组合使用为每个对像提供多个等待s ...

  7. Java中的守护线程 & 非守护线程(简介)

    Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...

  8. Java多线程编程之守护线程

    Java的线程分为两种,一个是用户线程,一个是守护线程.守护线程守护的对象就是用户线程,当用户线程结束后,守护它的守护线程也就会结束.二者的本质基本是一样的,唯一区别在于何时结束. 用户线程:直到自己 ...

  9. JAVA笔记13__创建线程/线程休眠/等待线程终止/线程中断/守护线程

    /** * 线程:是进程的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少有一个进程(单线程程序) * 多线程两种实现方法:1.继承Thread类 2.实现Runnable ...

随机推荐

  1. 调整ESX的VMFS磁盘格式的块大小,让单个虚拟磁盘支持更大容量

    调整ESX的VMFS磁盘格式的块大小,让单个虚拟磁盘支持更大容量 前因:客户搭建了VMware ESX企业版的测试平台:有一天接到一个需求,是测试数据库的,需要一个300G的磁盘. 解决过程: 1.按 ...

  2. D2.Reactjs 操作事件、状态改变、路由

    下面内容代码使用ES6语法 一.组件的操作事件: 1.先要在组件类定义内定义操作事件的方法,如同event handler.若我需要监听在组件内的Button的点击事件onClick,首先定义监听方法 ...

  3. Switch图形练习

    //package IfAndSwitchs;import java.util.Scanner; public class Mianji { public static void main(Strin ...

  4. Ext JS 4 老特征:statics 静态的变量和方法

    l   一.静态的变量和静态的方法 [译文原创Learning Ext JS 4 第51页] Statics的方法只属于类本身,而不属于任何一个实例,这就决定了我们是在定义类的内部来用statics方 ...

  5. xcode6 使用pch出错解决办法

    1down vote If you decide to add a .pch file manually and you want to use Objective-C just like befor ...

  6. java.io.IOException: Cannot run program "jad"

    今天调试google tag manager, 需要看看google analytics source code,无奈没有源码,装个一个插件ejad 还是不行: java.io.IOException ...

  7. 清除缓存,计算Sql Server查询效率

    --优化之前 DBCC FREEPROCCACHE DBCC DROPCLEANBUFFERS SET STATISTICS IO ON select Dtime,Value from dbo.his ...

  8. 《java集合概述》

    JAVA集合概述: Collection: |---List有序的:通过索引就可以精确的操作集合中的元素.元素是可以重复的. List提供了增删改查的动作. 增加add(element) add(in ...

  9. MySQL数据库5 - 插入数据,修改数据,删除数据

    一.插入数据 1. 所有列都插入值 INSERT [INTO] TABLE_NAME VALUES(V1,V2....Vn); 特点:列值同数,列值同序 eg: insert into users v ...

  10. windows下无法创建django工程的问题

    环境:python2.7  django1.7 安装好django后,将C:\Python27\Lib\site-packages\Django-1.7.7-py2.7.egg\django\bin; ...