文档章节

Java并发编程初级篇(六):守护线程

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/23 15:03
字数 809
阅读 42
收藏 0

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.

 

© 著作权归作者所有

共有 人打赏支持
阿拉德大陆的魔法师
粉丝 25
博文 91
码字总数 83019
作品 0
西城
程序员
私信 提问
JAVA多线程和并发基础面试问答

原文链接 译文连接 作者:Pankaj 译者:郑旭东 校对:方腾飞 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢...

雷神雨石
2014/07/19
0
2
JAVA多线程和并发基础面试问答

多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题。(校对注:...

LCZ777
2014/05/26
0
0
JAVA多线程和并发基础面试问答

Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一...

hanzhankang
2014/01/20
0
0
JAVA多线程和并发基础面试问答

Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一...

清风傲剑
2014/12/06
0
0
18《Java核心技术》之一个线程两次调用start()方法会出现什么情况?

一、提出问题 今天我们来深入聊聊线程,相信大家对于线程这个概念都不陌生,它是 Java 并发的基础元素,理解、操纵、诊断线程是 Java 工程师的必修课,但是你真的掌握线程了吗? 今天我们要一...

飞鱼说编程
11/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Maven 依赖范围(Dependency Scope)

Dependency Scope Dependency scope is used to limit the transitivity of a dependency, and also to affect the classpath used for various build tasks. 依赖范围用于限制依赖项的传递性......

晨猫
10分钟前
0
0
细述hbase协处理器

1.起因(Why HBase Coprocessor) HBase作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执行求和、计数、排序等操作。比如,在旧版本的(<0.92)Hbase中,统计数据表的...

微笑向暖wx
23分钟前
1
0
【实践】如何获得Rinkeby网络的测试以太币

当把智能合约部署到Rinkeby Test Network时,需要获得测试以太币。其网络获取测试以太币的方法同Ropsten Test Network有些不同,本文详细讲解一下。 1 访问网站 访问rinkeby网络(https://w...

HiBlock
45分钟前
1
0
Logback中如何自定义灵活的日志过滤规则

当我们需要对日志的打印要做一些范围的控制的时候,通常都是通过为各个Appender设置不同的Filter配置来实现。在Logback中自带了两个过滤器实现:ch.qos.logback.classic.filter.LevelFilter...

程序猿DD
51分钟前
3
0
ES6中let 和 const 的新特性

在javascript中,我们都知道使用var来声明变量。javascript是函数级作用域,函数内可以访问函数外的变量,函数外不能访问函数内的变量。 ECMAScript 6 是 JavaScript 语言教程,全面介绍 EC...

peakedness丶
59分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部