文档章节

守护线程的创建和运行

柳哥
 柳哥
发布于 2015/04/25 00:55
字数 921
阅读 282
收藏 5
点赞 0
评论 1

Java里有一种特殊的线程叫做守护(daemon)线程。这种线程的优先级很低,通常来说,当同一个应用程序里没有其它的线程运行的时候,守护线程才运行。当守护线程是程序中唯一运行的线程时,守护线程执行结束后,JVM也就结束了这个程序。

因为这种特性,守护线程通常被用来做为同一程序中普通线程(也称为用户线程)的服务提示者。它们通常是无限循环的,以等待服务请求或执行线程的任务。它们不能做重要的工作,因为我们不可能知道守护线程什么时候能够获取CPU时钟,并且,在没有其他线程运行的时候,守护线程随时可能结束。一个典型的守护线程是java的垃圾回收器(Garbage Collector)。

范例程序包含两个线程:一个是用户线程,它将事件写入到一个队列中;另一个是守护线程,它将管理这个队列,如果生成的事件超过10秒钟,就会被移除。

package concurrency;

import java.util.Date;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

public class Main1 {
    public static void main(String[] args) {
        LinkedBlockingDeque<Event> deque = new LinkedBlockingDeque<Event>();
        WriterTask writer = new WriterTask(deque);
        for(int i = 0;i < 3; i++){
            Thread thread = new Thread(writer);
            thread.start();
        }
        CleanerTask cleaner = new CleanerTask(deque);
        cleaner.start();
    }
}

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;
    }
}

class WriterTask implements Runnable{
    private LinkedBlockingDeque<Event> deque;
    public WriterTask(LinkedBlockingDeque<Event> deque){
        this.deque = deque;
    }
    public void run() {
        for(int i = 1; i <= 20; i++){
            Event event = new Event();
            event.setDate(new Date());
            event.setEvent(String.format("The thread %s has generated an event", 
                Thread.currentThread().getId()));
            deque.addFirst(event);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class CleanerTask extends Thread{
    private LinkedBlockingDeque<Event> deque;
    public CleanerTask(LinkedBlockingDeque<Event> deque){
        this.deque = deque;
        this.setDaemon(true);
    }
    @Override
    public void run() {
        while(true){
            Date date = new Date();
            clean(date);
        }
    }
    private void clean(Date date){
        long difference;
        boolean delete;
        if(deque.size() == 0) return;
        delete = false;
        do {
            Event e = deque.getLast();
            difference = date.getTime() - e.getDate().getTime();
            if(difference > 10000){
                System.out.printf("Cleaner: %s\n", e.getEvent());
                deque.removeLast();
                delete = true;
            }
        } while (difference > 10000);
        if(delete){
            System.out.printf("Cleaner: Size of the queue : %d\n", deque.size());
        }
    }
}

对程序的运行输出进行分析之后,我们会发现,队列中的对象会不断增长直到30个,然后到程序结束,队列的长度维持在27~30之间。

这个程序有3个WriterTask线程,每个线程向队列写入一个事件,然后休眠1秒钟。在第一个10秒钟内,队列中有30个事件,直到3个WriterTask都休眠后,CleanerTask才开始执行,但是它没有删除任何事件。因为所有的事件都小于10秒钟。在接下来的运行中,CleanerTask每秒删除3个对象,同时WriterTask会写入3个对象,所以队列的长度一直介于27~30之间。

setDaemon()方法只能在start()方法被调用之前设置。一旦线程开始运行,将不能再修改守护状态。isDaemon()方法被用来检查一个线程是不是守护线程,返回值true,表示这个线程是守护线程; false表示这个线程是用户线程。

注意:1. thread.setDaemon(true)必须在thread.start()之前设置。2. 在Daemon线程中产生的新线程也是Daemon的。新创建一个新Thread对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护线程。3. 当用户线程(非守护线程)全部结束,则守护线程也随即结束,否则守护线程将一直执行(不管你的守护线程业务逻辑是不是while(true)这样的死循环)。

© 著作权归作者所有

共有 人打赏支持
柳哥
粉丝 201
博文 394
码字总数 347782
作品 0
杭州
技术主管
加载中

评论(1)

曾经的十字镐
曾经的十字镐
这不是吊胃口么。6
java中守护线程与用户线程

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

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

JAVA多线程05-基础篇-守护线程

本节摘要:介绍守护线程,代码示例 一、守护线程 thread 类中有一个isDaemon的布尔变量,如果isDaemon=true代表该线程为守护线程,否则为用户线程 1.1 守护线程特点 当所有用户线程结束时,程...

x_coder ⋅ 2017/10/23 ⋅ 0

Java 多线程回顾

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

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

《深入Java虚拟机》——Java虚拟机读书笔记

1、Java虚拟机的生命周期 如果在同一台计算机上同时运行三个Java程序,将得到三个Java虚拟机实例。 在Java虚拟机内部有两种线程,守护线程和非守护线程。守护线程通常是由虚拟机自己使用的,...

亭子happy ⋅ 2014/04/11 ⋅ 0

多线程学习笔记(六)

在操作系统中,线程可以划分优先级,优先级较高的线程得到的CPU资源越多,也就是CPI优先执行优先级较高的线程对象中的任务. 设置线程优先级有助于帮线程规划器确定在下一次选择哪一个线程来优先...

scymore ⋅ 2016/08/31 ⋅ 0

学习笔记2:java中Thread类与线程的创建

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。 每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。...

牧羊人Berg ⋅ 2015/10/15 ⋅ 0

Azureus源码剖析(四)

AEThread只是一个简单的线程类,提供一个抽象方法runSupport 供我们重写,相必之下,AEThread2有几个改进的地方:1)加入了运行锁机制,运行线程和等待线程的结束这两个操作需要争抢运行锁,若...

嗯哼9925 ⋅ 01/07 ⋅ 0

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

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

ihaolin ⋅ 2014/03/30 ⋅ 0

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

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

angel_kitty ⋅ 2017/10/25 ⋅ 0

Java Thread源码分析

1、Runnable接口源码: 1 public interface Runnable { 2 public abstract void run(); 3 }   2、Thread类与Runnable接口的继承关系 1 public class Thread implements Runnable{ 2 3 }  ......

solar.xie ⋅ 2015/10/13 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

骰子游戏代码开源地址

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

算法之名 ⋅ 40分钟前 ⋅ 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

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部