文档章节

并发编程实战 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
海淀
程序员
私信 提问
java中守护线程与用户线程

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

今天你不奋斗明天你就落后
2017/09/29
0
0
Java 多线程回顾

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

五大三粗
2015/11/25
9
0
JAVA并发编程——守护线程(Daemon Thread)

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

月下狼
2015/08/20
0
0
守护线程的理解

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

浮躁的码农
2016/02/22
17
0
Java并发基础你需要知道的基础知识

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

异步社区
05/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

当程序员有了中年危机 你会发现你就是个屁

前言 程序员是一个怎样的存在?引用一句鸡汤的名言来说:你以为你用双手改变了世界,实际上是苍老了自己。为什么我今天会抛出这个话题,其实我也是一个懵懂的少年,我也曾经为了成为一名程序...

架构师springboot
5分钟前
0
0
大型网站B2C商城项目实战+MongoDB+Redis+zookeeper+MySQL

本文列出了当今计算机软件开发和应用领域最关键部分,如果你想保证你现在以及未来的几年不失业,那么你最好跟上这些技术的发展。虽然你不必对这十种技术样样精通,但至少应该对它们非常熟悉。...

java知识分子
5分钟前
0
0
大型企业网络系统集成方案如何设计?

网络系统集成是企业实现无纸化办公和即时通讯办公的基础建设,在以生产效率为核心竞争力的市场中,企业想要快速获取信息并有效提高企业工作效率及业务能力,企业网络系统集成是必不可少的,由...

Java干货分享
6分钟前
0
0
Spring应用学习——IOC

1. Spring简介 1. Spring的出现是为了取代EJB(Enterprise JavaBean)的臃肿、低效、脱离现实的缺点。Spring致力于J2EE应用的各层(表现层、业务层、持久层)的解决方案,Spring是企业应用开...

江左煤郎
7分钟前
0
0
用Redis轻松实现秒杀系统

导论 曾经被问过好多次怎样实现秒杀系统的问题。昨天又在CSDN架构师微信群被问到了。因此这里把我设想的实现秒杀系统的价格设计分享出来。供大家参考。 秒杀系统的架构设计 秒杀系统,是典型...

James-
15分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部