您的位置:首页 > 编程语言 > Java开发

java多线程之守护线程和用户线程

2017-07-22 13:43 603 查看
        Java中的线程分为两类:守护线程和用户线程,守护线程被称为后台线程、用户线程被称为前台线程。守护线程一般被用来服务用户线程,两者之间的区别就是体现在JVM的运行上,当所有的用户线程结束,JVM会自动退出,这时候系统服务停止运行,守护线程自然也只能被迫停止。反之,守护线程全部结束不一定会导致JVM退出。

        守护线程和用户线程在使用上区别不大,守护线程只需要在使用时执行this.setDaemon(true)方法,且这个方法必须放在this.start()方法之前执行,否则会抛出IllegalThreadStateException异常,JDK源码中此方法上的注释也已经明确指出使用时的注意事项。

/**
* Marks this thread as either a daemon thread or a user thread. The
* Java Virtual Machine exits when the only threads running are all
* daemon threads.
* <p>
* This method must be called before the thread is started.
* <p>
* This method first calls the <code>checkAccess</code> method
* of this thread
* with no arguments. This may result in throwing a
* <code>SecurityException </code>(in the current thread).
*
* @param on if <code>true</code>, marks this thread as a
* daemon thread.
* @exception IllegalThreadStateException if this thread is active.
* @exception SecurityException if the current thread cannot modify
* this thread.
* @see #isDaemon()
* @see #checkAccess
*/
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
下面用一个例子来比较下守护线程和用户线程的执行情况:

package com.zw;

/**
* 守护线程和用户线程
* @author Administrator
* 用户线程结束,JVM也就退出了,守护线程会立刻终止
*/
public class TestDaemon {

public static void main(String[] args) {

MyUserThread m = new MyUserThread();
MyUserThread2 m2 = new MyUserThread2();
MyDaemonThread md = new MyDaemonThread(m, m2);
md.setDaemon(true); //设置md为守护线程
md.start();
}
}

/**
* 守护线程
* @author Administrator
*
*/
class MyDaemonThread extends Thread {

MyUserThread m = null;
MyUserThread2 m2 = null;

MyDaemonThread(MyUserThread m,MyUserThread2 m2) {
this.m = m;
this.m2 = m2;
m.start();
m2.start();
}

@Override
public void run() {
// TODO Auto-generated method stub
super.run();
while(true) {
try {
Thread.sleep(1000
4000
);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("守护线程 " + m.getI());
}
}
}

/**
* 用户线程
* @author Administrator
*
*/
class MyUserThread extends Thread {
private int i = 0;

public int getI()
{
return i;
}

@Override
public void run() {
// TODO Auto-generated method stub
super.run();
while(i < 5) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("用户线程 " + i++);
}
}
}

class MyUserThread2 extends Thread {
private int i = 0;

public int getI()
{
return i;
}

@Override
public void run() {
// TODO Auto-generated method stub
super.run();
while(i < 10) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("用户线程2 " + i++);
}
}
}
执行结果:

用户线程          0

用户线程2     0
守护线程          1

用户线程          1
守护线程          2

用户线程2     1

用户线程          2
守护线程          3

用户线程2     2

用户线程          3
守护线程          4

用户线程2     3

用户线程          4
守护线程          5

用户线程2     4
守护线程          5

用户线程2     5
守护线程          5

用户线程2     6
守护线程          5

用户线程2     7
守护线程          5

用户线程2     8
守护线程          5

用户线程2     9

        上面的实例中启动了3个线程,一个守护线程md,两个用户线程m,m2。守护线程中无限循环执行输出,线程m执行结束时,守护线程还在自我循环中,但是当m2也结束时,守护线程也跟着停止了,这是因为m和m2两个用户线程全部结束,JVM检测到没有用户线程在执行,也就自动退出。JVM退出了,守护线程没了依托,也只能被迫停止。

        Java中的GC线程就是典型的守护线程,当系统停止了对象的创建,GC没有对象可回收,就会随着JVM退出而退出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: