并发编程实战 1.6. 守护线程 - Daemon线程

Java里有一种特殊的线程叫守护线程(Daemon)。这种线程的优先级很低,通常,当同一个应用程序里没有其他线程运行的时候,守护线程才运行。当没有其他线程的时候,守护线程执行结束后,jvm也将结束这个程序了。

因为这种特性,通常作为普通线程的服务提供者。它通常时无限循环的,以等待服务请求或者执行线程的任务。

它不能做重要的任务,因为我们不可能知道守护线程什么时候执行。

典型的例子就是java的垃圾回收器

范例:两个线程: 1. 普通线程: 每秒往deque里面添加Event; 2. 守护线程: 每十秒清除一次十秒前的Event;

普通进程:

package com.rr.current2.c1_6_daemon.test;

import java.util.Date;
import java.util.Deque;
import java.util.concurrent.TimeUnit;

/**
 * Created by Isaac on 16-5-10.
 * 1. 普通线程: 每秒往deque里面添加Event
 */
public class Task implements Runnable {
    private Deque<Event> deque;

    public Task(Deque<Event> deque) {
        this.deque = deque;
    }

    @Override
    public void run() {

        for (int i = 0, len = 100; i < len; i++) {
            Date date = new Date();
            synchronized (this) {
                deque.addFirst(new Event(date,
                                         String.format("%s %s (%d)!",
                                                       Thread.currentThread().getName(), date, i)));
            }
            System.out.printf("%s 创建了一个事件(%d)!\n",
                              Thread.currentThread().getName(), i);
            try {
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }
}

守护进程:

package com.rr.current2.c1_6_daemon.test;

import java.util.Date;
import java.util.Deque;
import java.util.concurrent.TimeUnit;

/**
 * Created by Isaac on 16-5-10.
 * 2. 守护线程: 每十秒清除一次十秒前的Event
 */
public class DaemonThread extends Thread {
    private Deque<Event> deque;

    public DaemonThread(Deque<Event> deque) {
        this.deque = deque;
        //可以在构造器中,设置守护进程
        //setDaemon(true);
    }

    @Override
    public void run() {
        boolean flag;
        Event event;
        Date date;
        while (true) {
            //等待10秒
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //从最后面取数据
            flag = true;
            date = new Date();
            while (flag) {
                if(deque.size() == 0)
                    return;
                event = deque.getLast();
                //大于十秒钟
                if (date.getTime() - event.getCreatedTime().getTime() > 10000) {
                    deque.removeLast();
                } else {
                    flag = false;
                }
            }

            System.out.println("***************** 当前deque *****************");

            for (Event aDeque : deque) {
                System.out.println(aDeque.getInfo());
            }

        }
    }
}

Event:

package com.rr.current2.c1_6_daemon.test;

import java.util.Date;

/**
 * Created by Isaac on 16-5-10.
 */
public class Event {
    private String info;
    private Date createdTime;

    public Event(Date createdTime, String info) {
        this.info = info;
        this.createdTime = createdTime;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public Date getCreatedTime() {
        return createdTime;
    }

    public void setCreatedTime(Date createdTime) {
        this.createdTime = createdTime;
    }

    @Override
    public String toString() {
        return "Event{" +
                "info='" + info + '\'' +
                ", createdTime=" + createdTime +
                '}';
    }
}

测试:

package com.rr.current2.c1_6_daemon.test;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;

/**
 * Created by Isaac on 16-5-10.
 * 两个线程:
 * 1. 普通线程: 每秒往deque里面添加Event
 * 2. 守护线程: 每十秒清除一次十秒前的Event
 */
public class Test {
    public static void main(String[] args) {
        Deque<Event> deque = new ArrayDeque<>();
        //普通进程
        Task task = new Task(deque);
        //开启三个普通进程
        for(int i = 0 , len = 3; i < len; i ++){
            new Thread(task).start();
        }

        //守护进程
        DaemonThread daemon = new DaemonThread(deque);
        //需要在start()之前,设置daemon;一旦线程开始运行,将不能再修改守护状态;
        daemon.setDaemon(true);
        daemon.start();

        System.out.println(daemon.isDaemon());

    }

    /**
     * java.util.ArrayDeque是Deque接口的动态数组实现,容量会按需扩展,线程不安全。
     * 作为栈使用比java.util.Stack快,作为队列使用比java.util.LinkedList快。
     * 大多数的操作消耗常数时间。
     */
    public void testDeque(){
        Deque<Integer> deque = new ArrayDeque<>();
        // 4, 3, 2, 1 -> []
//        deque.addFirst(1);
//        deque.addFirst(2);
//        deque.addFirst(3);
//        deque.addFirst(4);

        // [] <- 1, 2, 3, 4
//        deque.add(1);
//        deque.add(2);
//        deque.add(3);
//        deque.add(4);

        // [] <- 1, 2, 3, 4
//        deque.addLast(1);
//        deque.addLast(2);
//        deque.addLast(3);
//        deque.addLast(4);

        // [] <- 1, 2, 3, 4
//        deque.offer(1);
//        deque.offer(2);
//        deque.offer(3);
//        deque.offer(4);

        // 4, 3, 2, 1 -> []
//        deque.offerFirst(1);
//        deque.offerFirst(2);
//        deque.offerFirst(3);
//        deque.offerFirst(4);

        // [] <- 1, 2, 3, 4
//        deque.offerLast(1);
//        deque.offerLast(2);
//        deque.offerLast(3);
//        deque.offerLast(4);

        Iterator<Integer> it = deque.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

当把Task的休眠时间调小的时候,例如10ms,队列长度将不断增加,DaemonThread将不会被调用;

setDaemon()方法只能在start()方法被调用之前设置。一旦线程开始运行,将不能再修改守护状态了。

isDaemon()方法被用来检查一个线程是不是守卫线程,返回值为true表示这个线程时守护线程。

Daemon Thread 产生的新线程也是Daemon Thread。

转载于:https://my.oschina.net/u/659286/blog/673130

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值