文档章节

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

火犀牛
 火犀牛
发布于 2016/05/11 00:26
字数 1010
阅读 5
收藏 0
点赞 2
评论 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
海淀
程序员
java中守护线程与用户线程

Java线程分为两类分别为daemon线程(守护线程)和User线程(用户线程),在JVM启动时候会调用main函数,main函数所在的线程是一个用户线程,这个是我们可以看到的线程,其实JVM内部同时还启动...

今天你不奋斗明天你就落后 ⋅ 2017/09/29 ⋅ 0

JAVA并发编程——守护线程(Daemon Thread)

在Java中有两类线程:用户线程 (User Thread)、守护线程 (Daemon Thread)。 所谓守护 线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并...

月下狼 ⋅ 2015/08/20 ⋅ 0

Java 多线程回顾

做java web开发,一直以来比较依赖java框架和oracle数据库的功能。因为一般遇到高并发的情况并不多,企业内软件多半用户数不多,即使偶尔遇到,也都在oracle数据库中处理了。 对java的多线程...

五大三粗 ⋅ 2015/11/25 ⋅ 0

Java并发基础你需要知道的基础知识

多线程和并发编程是Java里面的核心内容,通常有以下一些概念需要重点掌握。 线程; 锁; 同步器; 并发容器和框架; Java并发工具类; 原子操作类; Executor框架(执行机制); 并发基础概念 ...

异步社区 ⋅ 05/30 ⋅ 0

守护线程的理解

在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程) Daemon的作用是为其他线程的运行提供便利服务,比如垃圾回收线程就是一个很称职的守护者。User和Daemon两者几乎没有区...

浮躁的码农 ⋅ 2016/02/22 ⋅ 0

JAVA7并发编程

1线程的创建与运行 接口Runnable 覆盖run方法 线程信息 thread中包含id name priorty status priorty中包括1到10,1最低,10最高 status状态有6种:new, runnable, blocked, waiting, time wa...

jiangmitiao ⋅ 2015/06/11 ⋅ 0

Java并发编程实战--笔记二

第5章:基础构建模块      ConcurrentHashMap 与其他并发容器一起增强了同步容器类:他们提供的迭代器不会抛出 ConcurrentModificationException ,因此不需要在迭代过程中对容器加锁。 ...

xunzaosiyecao ⋅ 2017/10/13 ⋅ 0

【Java学习笔记之三十四】超详解Java多线程基础

前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧。 正文 线程与进程 1 线程:进程中负...

angel_kitty ⋅ 2017/10/25 ⋅ 0

【Linux】Linux系统编程入门

作者:不洗碗工作室 - Marklux 出处:marklux.cn/blog/56 版权归作者所有,转载请注明出处 文件和文件系统 文件是linux系统中最重要的抽象,大多数情况下你可以把linux系统中的任何东西都理解...

不洗碗工作室 ⋅ 2017/11/14 ⋅ 0

java并发编程(六): 取消与关闭

取消与关闭: 如何正确,安全地取消或关闭任务。 任务取消: 若外部代码能在某个操作正常完成之前将其置入“完成”状态,则还操作是可取消的。 取消操作的原因: 1. 用户请求取消。 2. 有时间...

ihaolin ⋅ 2014/03/30 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

骰子游戏代码开源地址

因为阿里云现在服务器已经停用了,所以上面的配置已经失效。 服务端开源地址:https://gitee.com/goalya/chat4.git 客户端开源地址:https://gitee.com/goalya/client4.git 具体运行界面请参考...

算法之名 ⋅ 32分钟前 ⋅ 0

设计模式--装饰者模式

装饰者模式 定义 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。 通用类图 意图 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比...

gaob2001 ⋅ 今天 ⋅ 0

JavaScript零基础入门——(八)JavaScript的数组

JavaScript零基础入门——(八)JavaScript的数组 欢迎大家回到我们的JavaScript零基础入门,上一节课我们讲了有关JavaScript正则表达式的相关知识点,便于大家更好的对字符串进行处理。这一...

JandenMa ⋅ 今天 ⋅ 0

sbt网络问题解决方案

转自:http://dblab.xmu.edu.cn/blog/maven-network-problem/ cd ~/.sbt/launchers/0.13.9unzip -q ./sbt-launch.jar 修改 vi sbt/sbt.boot.properties 增加一个oschina库地址: [reposit......

狐狸老侠 ⋅ 今天 ⋅ 0

大数据,必须掌握的10项顶级安全技术

我们看到越来越多的数据泄漏事故、勒索软件和其他类型的网络攻击,这使得安全成为一个热门话题。 去年,企业IT面临的威胁仍然处于非常高的水平,每天都会看到媒体报道大量数据泄漏事故和攻击...

p柯西 ⋅ 今天 ⋅ 0

Linux下安装配置Hadoop2.7.6

前提 安装jdk 下载 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz 解压 配置 vim /etc/profile # 配置java环境变量 export JAVA_HOME=/opt/jdk1......

晨猫 ⋅ 今天 ⋅ 0

crontab工具介绍

crontab crontab 是一个用于设置周期性被执行的任务工具。 周期性执行的任务列表称为Cron Table crontab(选项)(参数) -e:编辑该用户的计时器设置; -l:列出该用户的计时器设置; -r:删除该...

Linux学习笔记 ⋅ 今天 ⋅ 0

深入Java多线程——Java内存模型深入(2)

5. final域的内存语义 5.1 final域的重排序规则 1.对于final域,编译器和处理器要遵守两个重排序规则: (1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用...

江左煤郎 ⋅ 今天 ⋅ 0

面试-正向代理和反向代理

面试-正向代理和反向代理 Nginx 是一个高性能的反向代理服务器,但同时也支持正向代理方式的配置。

秋日芒草 ⋅ 今天 ⋅ 0

Spring 依赖注入(DI)

1、Setter方法注入: 通过设置方法注入依赖。这种方法既简单又常用。 类中定义set()方法: public class HelloWorldOutput{ HelloWorld helloWorld; public void setHelloWorld...

霍淇滨 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部