Java并发编程初级篇(六):守护线程
Java并发编程初级篇(六):守护线程
阿拉德大陆的魔法师 发表于1年前
Java并发编程初级篇(六):守护线程
  • 发表于 1年前
  • 阅读 27
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 在Java中存在一种优先级很低的线程叫做守护线程。

Java中的提供的守护线程优先级很低。也就是说,当同一个应用中中没有其他线程运行的时候,守护线程才运行,当其他线程都已经终止后,守护线程成为了唯一的运行线程时,那么守护线程就会终止,JVM应用结束。

因为守护线程的特性,通常情况下守护线程是用来为普通线程提供服务的。它在结构设计上是无限循环的,并且不能够承担重要工作,因为我们不知道守护线程什么时候能够获取CPU时间,守护线程也不能够独立存在。在Java中,守护线程最典型的一个例子就是垃圾收集器(GC)。

在Java API中提供了Thread.setDaemon(true)方法把一个线程设置成守护线程。

下面我们来实现一个守护线程的例子,在这里例子中我们模拟一个生产者不断地向Deque中生产Event对象,然后模拟一个守护进程,它的作用就是检查Deque来保证Deque中的Event生产时间都是10秒内的。

首先我们定义一个Event对象,它有两个属性,一个是生产时间,一个是名称。

public class Event {
    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;
    }
}

下面我们定义一个生产者线程,用来不断地向Deque中生产Event对象,并记录生产时间。

public class ProducerTask implements Runnable {
    private Deque<Event> deque;

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

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            Event event = new Event();
            event.setDate(new Date());
            event.setEvent(Thread.currentThread().getName() + " Event:" + i);
            deque.addFirst(event);

            System.out.printf("%s: Produce one event %s.\n", Thread.currentThread().getName(), event.getEvent());

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

定义守护线程,保证Deque中生产的Event对象都是10秒内的。

public class GuardTask implements Runnable {
    private Deque<Event> deque;

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

    @Override
    public void run() {
        while (true) {
            Event event = deque.getLast();

            Date now = new Date();

            if (now.getTime() - event.getDate().getTime() > 10000) {
                deque.removeLast();

                System.out.printf("%s: Clean Deque %s. Deque size is %d.\n",
                        Thread.currentThread().getName(),
                        event.getEvent(),
                        deque.size());
            }
        }
    }
}

定义主方法类,启动三个生产者线程,并注册一个守护线程。

public class Main {
    public static void main(String[] args) {
        Deque<Event> deque = new ArrayDeque<Event>();

        Thread producer1 = new Thread(new ProducerTask(deque), "Producer-1");
        Thread producer2 = new Thread(new ProducerTask(deque), "Producer-2");
        Thread producer3 = new Thread(new ProducerTask(deque), "Producer-3");

        producer1.start();
        producer2.start();
        producer3.start();

        //创建守护线程
        Thread guard = new Thread(new GuardTask(deque), "Guard");
        guard.setDaemon(true);

        guard.start();
    }
}

查看日志,我们会发现因为守护线程的存在,保证了Deque中的Event数量稳定在了27-30个,最后当所有线程都结束后,守护线程也就结束了。

Producer-3: Produce one event Producer-3 Event:98.
Producer-2: Produce one event Producer-2 Event:98.
Producer-1: Produce one event Producer-1 Event:98.
Guard: Clean Deque Producer-3 Event:89. Deque size is 24.
Guard: Clean Deque Producer-2 Event:89. Deque size is 23.
Guard: Clean Deque Producer-1 Event:89. Deque size is 22.
Producer-3: Produce one event Producer-3 Event:99.
Producer-2: Produce one event Producer-2 Event:99.
Producer-1: Produce one event Producer-1 Event:99.
Guard: Clean Deque Producer-3 Event:90. Deque size is 24.
Guard: Clean Deque Producer-1 Event:90. Deque size is 23.

 

共有 人打赏支持
粉丝 21
博文 91
码字总数 83019
×
阿拉德大陆的魔法师
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: