守护(Daemon)线程的创建及运行

来源:互联网 发布:iphone屏幕录制软件 编辑:程序博客网 时间:2024/06/03 23:17

1、守护(Daemon)线程简介

在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程或服务线程) 。任何一个守护线程都是整个JVM中所有非守护线程的保姆,守护线程的优先级比较低,用于为系统中的其它对象和线程提供服务。

通过setDaemon(true)来设置线程为“守护线程”;将一个用户线程设置为守护线程的方式是在thread.start()之前用线程对象的setDaemon方法。

只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。

Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),当我们的程序中不再有任何运行的Thread,程序就不会再产生垃圾,垃圾回收器也就无事可做,所以当垃圾回收线程是JVM上仅剩的线程时,垃圾回收线程会自动离开。它始终在低级别的状态中运行,用于实时监控和管理系统中的可回收资源。

User和Daemon两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下Daemon Thread存在了,虚拟机也就退出了。 因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。那Java的守护线程是什么样子的呢。当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则JVM不会退出。

守护线程并非只有虚拟机内部提供,用户在编写程序时也可以自己设置守护线程。

2、代码事例

package com.xxx.util;import java.util.Date;/** * Created with IntelliJ IDEA. * Date: 15-3-30 * Time: 上午9:02 * To change this template use File | Settings | File Templates. */public class DaemonEntity {    private Date date;    private String event;    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }    public String getEvent() {        return event;    }    public void setEvent(String event) {        this.event = event;    }}
package com.xxx.util;import java.util.Date;import java.util.Deque;import java.util.concurrent.TimeUnit;/** * Created with IntelliJ IDEA. * Date: 15-3-30 * Time: 上午9:06 * To change this template use File | Settings | File Templates. */public class ThreadUser implements Runnable {    private Deque<DaemonEntity> deque;    public ThreadUser(Deque<DaemonEntity> deque){        this.deque = deque;    }    @Override    public void run() {        for(int i=1;i<100;i++){            DaemonEntity daemonEntity = new DaemonEntity();            daemonEntity.setDate(new Date());            daemonEntity.setEvent(String.format("The thread %s has generated an event\n",Thread.currentThread().getId()));            deque.addFirst(daemonEntity);            try {                TimeUnit.SECONDS.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}
package com.xxx.util;import java.util.Date;import java.util.Deque;/** * Created with IntelliJ IDEA. * Date: 15-3-30 * Time: 上午9:24 * To change this template use File | Settings | File Templates. */public class ThreadDaemon extends Thread {    private Deque<DaemonEntity> deque;    public ThreadDaemon(Deque<DaemonEntity> deque){        this.deque = deque;        setDaemon(true);//设置为守护线程    }    @Override    public void run(){        while (true){            Date date = new Date();            cleanDeque(date);        }    }    public void cleanDeque(Date date){        long difference;        boolean deleteFlag;        if(deque.size()==0){            return;        }        deleteFlag = false;        do{            DaemonEntity daemonEntity = deque.getLast();            difference = date.getTime()- daemonEntity.getDate().getTime();            if(difference>10000){                System.out.printf("Cleaner: size of the queue:%d\n",deque.size());                deque.removeLast();                deleteFlag = true;            }        }while (difference>10000);        if(deleteFlag){            System.out.printf("Cleaner: size of the queue:%d\n",deque.size());        }    }}
package com.xxx.util;import java.util.ArrayDeque;import java.util.Deque;/** * Created with IntelliJ IDEA. * Date: 15-3-30 * Time: 上午9:38 * To change this template use File | Settings | File Templates. */public class ThreadDaemonMain {    public static void main(String[] args){        Deque<DaemonEntity> deque = new ArrayDeque<DaemonEntity>();        ThreadUser threadUser = new ThreadUser(deque);        for(int i=0;i<3;i++){            Thread thread = new Thread(threadUser);            thread.start();        }        ThreadDaemon threadDaemon = new ThreadDaemon(deque);        threadDaemon.start();    }}
3、运行结果:


4、结论

守护线程在用户线程休眠时进行了删除操作,如果休眠时间越小,队列长度将增加,如果用户线程不休眠,守护线程没有删除对象就结束了。

0 0
原创粉丝点击