zoukankan      html  css  js  c++  java
  • java线程基础知识----java daemon线程

      java线程是一个运用很广泛的重点知识,我们很有必要了解java的daemon线程.

    1.首先我们必须清楚的认识到java的线程分为两类: 用户线程和daemon线程

      A.  用户线程: 用户线程可以简单的理解为用户定义的线程,当然包括main线程(以前我错误的认为main线程也是一个daemon线程,但是慢慢的发现原来main线程不是,因为如果我再main线程中创建一个用户线程,并且打出日志,我们会发现这样一个问题,main线程运行结束了,但是我们的线程任然在运行).

      B.  daemon线程: daemon线程是为我们创建的用户线程提供服务的线程,比如说jvm的GC等等,这样的线程有一个非常明显的特征: 当用户线程运行结束的时候,daemon线程将会自动退出.(由此我们可以推出下面关于daemon线程的几条基本特点)

    2. daemon 线程的特点: 

      A.  守护线程创建的过程中需要先调用setDaemon方法进行设置,然后再启动线程.否则会报出IllegalThreadStateException异常.(个人在想一个问题,为什么不能动态更改线程为daemon线程?有时间一个补上这个内容,现在给出一个猜测: 是因为jvm判断线程状态的时候,如果当前只存在一个线程Thread1,如果我们把这个线程动态更改为daemon线程,jvm会认为当前已经不存在用户线程而退出,稍后将会给出正确结论,抱歉!如果有哪位大牛看到,希望给出指点,谢谢!)

      B.  由于daemon线程的终止条件是当前是否存在用户线程,所以我们不能指派daemon线程来进行一些业务操作,而只能服务用户线程.

      C.  daemon线程创建的子线程任然是daemon线程.

    3. 针对上面给出的daemon线程的特点,我们进行如下验证:

      A.  对应上面的A特点:

    public class ThreadTest {
        public static void main(String[] args) throws InterruptedException {
            Thread thread1 = new Thread(new Thread2());
            thread1.start();
            thread1.setDaemon(true);
            Thread.sleep(10);
            System.out.println("用户线程退出");
        }
    }
    class Thread2 implements Runnable{
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println("1+1="+(1+1));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    运行结果:
    Exception in thread "main" java.lang.IllegalThreadStateException
        at java.lang.Thread.setDaemon(Thread.java:1352)
        at ThreadTest.main(ThreadTest.java:5)
    1+1=2

      通过上面的例子我们可以发现,我们并不能动态的更改线程为daemon线程,源码解释如下:

    java源码:
        public final void setDaemon(boolean on) {
            checkAccess();
            if (isAlive()) {
                throw new IllegalThreadStateException();
            }
            daemon = on;
        }

      我们可以发现,在源码中如果我们的线程状态是alive的,我们的程序就会抛出异常.

      B.对应上面的B特点:

      

    public class ThreadTest {
        public static void main(String[] args) throws InterruptedException {
            Thread thread1 = new Thread(new Thread2());
            thread1.setDaemon(true);
            thread1.start();
            Thread.sleep(10);
            System.out.println("用户线程退出");
        }
    }
    class Thread2 implements Runnable{
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println("1+1="+(1+1));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    运行结果: 用户线程退出

      通过上面的例子我们可以看到,我们在daemon线程中进行相关的计算工作,但是我们并没有获取计算结果,因为用户线程main已经运行结束.

      C.对应上面的C特点:

      

    public class ThreadTest {
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(new Thread2());
            thread.setDaemon(true);
            thread.start();
            System.out.println("Thread是否时daemon线程"+thread.isDaemon());
            Thread.sleep(100);
            System.out.println("用户线程退出");
        }
    }
    class Thread2 implements Runnable{
        @Override
        public void run() {
            Thread1 thread1 = new Thread1();
            thread1.start();
            System.out.println("Thread1是否是daemon线程"+thread1.isDaemon());
        }
    }
    class Thread1 extends Thread{
        public void run () {
            System.out.println("dosomething");
        }
    }
    运行结果:
    Thread是否时daemon线程true
    Thread1是否是daemon线程true
    dosomething
    用户线程退出

      源码解析:

     private void init(ThreadGroup g, Runnable target, String name,
                          long stackSize, AccessControlContext acc) {
           ......
            this.daemon = parent.isDaemon();
            this.priority = parent.getPriority();
           ......
        }

      在进行Thread初始化的时候,会获取父进程的isDaemon来复制子进程的daemon.

  • 相关阅读:
    0719PHP基础:PDO
    0717PHP基础:面向对象
    0716PHP基础:面向对象
    0715JS基础:ajax
    0715PHP练习:文件操作
    0715PHP基础:文件操作
    0629正则表达式:基础
    0628正则表达式:练习
    zTree简单使用和代码结构
    servlet
  • 原文地址:https://www.cnblogs.com/liboBlog/p/6431733.html
Copyright © 2011-2022 走看看