文档章节

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

火犀牛
 火犀牛
发布于 2016/05/11 00:26
字数 1010
阅读 5
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

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。

火犀牛
粉丝 0
博文 27
码字总数 12180
作品 0
海淀
程序员
私信 提问
加载中
请先登录后再评论。
用vertx实现高吞吐量的站点计数器

工具:vertx,redis,mongodb,log4j 源代码地址:https://github.com/jianglibo/visitrank 先看架构图: 如果你不熟悉vertx,请先google一下。我这里将vertx当作一个容器,上面所有的圆圈要...

jianglibo
2014/04/03
4.3K
3
Swift百万线程攻破单例(Singleton)模式

一、不安全的单例实现 在上一篇文章我们给出了单例的设计模式,直接给出了线程安全的实现方法。单例的实现有多种方法,如下面: class SwiftSingleton { } 这段代码的实现,在shared中进行条...

一叶博客
2014/06/20
3.5K
16
WSGI Web服务器--UV-Web

uv-web是一个轻量级的支持高并发的WSGI Web服务器,基于libuv构建,部分代码源于开源项目bjoern,本质是python的C扩展,所以适用于部署绝大部分 python web应用(如 Django) 特性 兼容 HTTP 1...

Jone.x
2013/03/04
1.8K
0
Password Manager Daemon

pwmd(Password Manager Daemon) 通过 Unix domain socket 提供服务,数据存储在加密的 XML 文件中,客户端必须提供密钥才能修改。支持多线程,可同时允许多个客户端同时连接。 特性 通过 ...

匿名
2013/03/12
436
0
开源数据访问组件--Smark.Data

Smark.Data是基于Ado.net实现的数据访问组件,提供基于强类型的查询表达式进行灵活的数据查询,统计,修改和删除等操作;采用基于条件驱动的操作模式,使数据操作更简单轻松;内部通过标准SQL...

泥水佬
2013/03/12
2.6K
0

没有更多内容

加载失败,请刷新页面

加载更多

EasyDL入驻社区果蔬店 离线识别秒级智能结算

传统收银方式高成本低效率 急需转型 500米商圈概念被越来越多的企业关注,在中国,一个社区就有可能成为一个商圈,蕴藏着巨大的商机。而在社区中,果蔬作为人们每天都要采购的高频消费商品,...

百度智能云
06/10
0
0
rabbitmq集群环境安装配置

一、主机清单 2台机器同时执行下面安装步骤 10.0.0.216 shiguang-rabbitmq-01 10.0.0.223 shiguang-rabbitmq-02 注意:请将上面内容加入2台机器 /etc/hosts (集群环境必须要加) 1、安装erlan...

caozhangming
2019/08/09
0
0
【rabbitmq-Php】-发布Publish 与订阅Subscribe

发布/订阅,使用扇型交换机(fanout) composer.json ### composer.json { "require": { "php-amqplib/php-amqplib": ">=2.9.0" }} 发布端(Publish) /** * rabbitmq......

DEPAKIN
19分钟前
11
0
如何在PHP中进行重定向? - How do I make a redirect in PHP?

问题: Is it possible to redirect a user to a different page through the use of PHP? 是否可以通过使用PHP将用户重定向到其他页面? Say the user goes to www.example.com/page.php an......

法国红酒甜
29分钟前
9
0
一周面试了 30 人,通过 2 人,面试面到我心态爆炸…

Java技术栈 www.javastack.cn 打开网站看更多优质文章 因技术团队人员调整及项目组扩编,需要招几个 Java 程序员,3~5年左右,领导要求的是能力要比现有的大部分技术人员要强,并且宁缺勿滥...

Java技术栈
05/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部