守护线程

在java中有一类线程,专门在后台提供服务,此类线程无需显式关闭,当程序结束了,它也就结束了,这就是守护线程 daemon thread。如果还有非守护线程的线程在执行,它就不会结束。 守护线程有何用处呢?让我们来看个实践中的例子。

  在我们的系统中经常应用各种配置文件(黑名单,禁用词汇),当修改配置文件后,一般要重启服务,系统才能够加载;当重启服务的代价比较高的情况下,这种加载方式不能满足我们的要求,这个时候守护线程该发挥它的作用了,它可以实时加载你的配置文件,无需重启。(当然,相当重要的配置文件,不推荐实时加载)

package com.ikon.thread.daemon;

import java.io.File;
import java.util.*;

/**

  • 文件监测
  • @author ikon99999
  • */

public abstract class FileWatchdog extends Thread {

static final public long DEFAULT_DELAY = 20*1000;

protected HashMap fileList;

protected long delay = DEFAULT_DELAY;

boolean warnedAlready = false;

boolean interrupted = false;

public static class Entity
{

    File file;
    long lastModify;
    Entity(File file,long lastModify)
    {
        this.file = file;
        this.lastModify = lastModify;
    }

}

protected FileWatchdog() {

  fileList = new HashMap ();
setDaemon(true);

}

public void setDelay(long delay) {

this.delay = delay;

}

public void addFile(File file)
{

    fileList.put(file.getAbsolutePath(),new Entity(file,file.lastModified()));     

}

public boolean contains(File file)
{

    if( fileList.get(file.getAbsolutePath()) != null) return true;
    else return false;

}

abstract protected void doOnChange(File file);

protected void checkAndConfigure() {

  HashMap map = (HashMap)fileList.clone();
  Iterator it = map.values().iterator();

  while( it.hasNext())
  {

        Entity entity = (Entity)it.next();

        boolean fileExists;
        try {
          fileExists = entity.file.exists();
        } catch(SecurityException  e)
        {
          System.err.println ("Was not allowed to read check file existance, file:["+ entity.file .getAbsolutePath() +"].");
          interrupted = true;
          return;
        }

        if(fileExists)
        {

          long l = entity.file.lastModified(); // this can also throw a SecurityException
          if(l > entity.lastModify) {           // however, if we reached this point this
                entity.lastModify = l;              // is very unlikely.
                newThread(entity.file);
          }
        }
        else
        {
            System.err.println ("["+entity.file .getAbsolutePath()+"] does not exist.");
        }
  }

}

private void newThread(File file)
{

  class MyThread extends Thread
  {
        File f;
        public MyThread(File f)
        {
            this.f = f;
        }

        public void run()
        {
            doOnChange(f);
        }
  }

  MyThread mt = new MyThread(file);
  mt.start();

}

public void run()
{

while(!interrupted) {
  try {
    Thread.currentThread().sleep(delay);
  } catch(InterruptedException e) {
// no interruption expected
  }
  checkAndConfigure();
}

}
}

FileWatchdog是个抽象类,本身是线程的子类;在构造函数中设置为守护线程;
此类用hashmap维护着一个文件和最新修改时间值对,checkAndConfigure()方法用来检测哪些文件的修改时间更新了,如果发现文件更新了则调用doOnChange方法来完成监测逻辑;doOnChange方法是我们需要实现的;看下面关于一个黑名单服务的监测服务:

1package com.ikon.thread.daemon;
2
3import java.io.File;
4
5/**
6 * 黑名单服务
7 * @author ikon99999
8 * 2011-3-21
9 */
10public class BlacklistService {
11 private File configFile = new File("c:/blacklist.txt");
12
13 public void init() throws Exception{
14 loadConfig();
15 ConfigWatchDog dog = new ConfigWatchDog();
16 dog.setName("daemon_demo_config_watchdog");//a
17 dog.addFile(configFile);//b
18 dog.start();//c
19 }
20
21 public void loadConfig(){
22 try{
23 Thread.sleep(1*1000);//d
24
25 System.out.println("加载黑名单");
26 }catch(InterruptedException ex){
27 System.out.println("加载配置文件失败!");
28 }
29 }
30
31 public File getConfigFile() {
32 return configFile;
33 }
34
35 public void setConfigFile(File configFile) {
36 this.configFile = configFile;
37 }
38
39
40 private class ConfigWatchDog extends FileWatchdog{
41
42 @Override
43 protected void doOnChange(File file) {
44 System.out.println("文件"+file.getName()+"发生改变,重新加载");
45 loadConfig();
46 }
47
48 }
49
50 public static void main(String[] args) throws Exception {
51 BlacklistService service = new BlacklistService();
52 service.init();
53
54 Thread.sleep(60601000);//e
55 }
56}
57

    ConfigWatchDog内部类实现了doOnChange(File file)方法,当文件被修改后,watchdog调用doOnChange方法完成重新加载操作;
    在blackservice的init方法中初始化watchdog线程;
    d:模拟文件加载耗时
    e:主要是防止主线程退出;

    其实上面的FileWatchdog就是取自log4j;

本文出自seven的测试人生公众号最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-10-24 21:56:44

守护线程的相关文章

ASPNET中实现在线用户检测(使用后台守护线程)

后台|在线 以下是我的类文件, //online.cs(用户在线检测)/*程序实现思路: 该用户有以下几个属性:name:用户名sessionID:用户ID,通过它唯一表示一个用户iswhere :附加信息,用户当前所在位置lasttime:用户登陆时间curtime:本次刷新时间 在客户端,使用一个IFRAME,装载一个刷新页面,每隔XX秒更新一下他的名字对应的curtime,就表示他仍然在 在服务器端,建立一个守护线程,每隔固定时间就运行一遍,然后判断当前所有用户列表中的时间间隔是否超出了规

Java多线程:“基础篇”10之线程优先级和守护线程

1. 线程优先级的介绍 java 中的线程优先级的范围是1-10,默认的优先级是5."高优先级线程"会优先于 "低优先级线程"执行. java 中有两种线程:用户线程和守护线程.可以通过isDaemon()方法来区别它们:如果返回false, 则说明该线程是"用户线程":否则就是"守护线程". 用户线程一般用户执 行用户级任务,而守护线程也就是"后台线程",一般用来执行后台任务.需要注意的是: Java虚拟

Java线程:线程的调度-守护线程

守护线程使用的情况较少,但并非无用,举例来说,JVM的垃圾回收.内存管理等线程都是守护线程.还有就是在做数据库应用时候,使用的数据库连接池,连接池本身也包含着很多后台线程,监控连接个数.超时时间.状态等等. setDaemon方法的详细说明: public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程.当正在运行的线程都是守护线程时,Java 虚拟机退出. 该方法必须在启动线程前调用. 该方法首先调用该线程的 checkAccess 方法,且不

线程管理:守护线程的创建和运行

线程管理:守护线程的创建和运行 守护线程的创建和运行Java有一种特别的线程叫做守护线程.这种线程的优先级非常低,通常在程序里没有其他线程运行时才会执行它.当守护线程是程序里唯一在运行的线程时,JVM会结束守护线程并终止程序. 根据这些特点,守护线程通常用于在同一程序里给普通线程(也叫使用者线程)提供服务.它们通常无限循环的等待服务请求或执行线程任务.它们不能做重要的任务,因为我们不知道什么时候会被分配到CPU时间片,并且只要没有其他线程在运行,它们可能随时被终止.JAVA中最典型的这种类型代表

timer的用法-javax.swing.Timer中的线程是不是守护线程,盼大神指点

问题描述 javax.swing.Timer中的线程是不是守护线程,盼大神指点 这是源代码 import java.awt.*; import java.awt.event.*; import javax.swing.*; class mytime implements ActionListener { Timer time; int n=0; mytime() { time=new Timer(1000,this); time.start(); } public void actionPerf

线程管理(七)守护线程的创建和运行

守护线程的创建和运行 Java有一种特别的线程叫做守护线程.这种线程的优先级非常低,通常在程序里没有其他线程运行时才会执行它.当守护线程是程序里唯一在运行的线程时,JVM会结束守护线程并终止程序. 根据这些特点,守护线程通常用于在同一程序里给普通线程(也叫使用者线程)提供服务.它们通常无限循环的等待服务请求或执行线程任务.它们不能做重要的任务,因为我们不知道什么时候会被分配到CPU时间片,并且只要没有其他线程在运行,它们可能随时被终止.JAVA中最典型的这种类型代表就是垃圾回收器. 在这个指南中

redis.conf 配置文件 中 daemonize 守护线程

问题描述 redis.conf 配置文件 中 daemonize 守护线程 在学习redis的过程中,看到介绍redis的配置文件redis.conf中 daemonize 可以用来指定redis 是否要用守护线程的方式启动. 请问redis 的守护线程启动和非守护线程启动 有什么启动 ps:目前在测试的时候是使用screen 启动,启动成功后退出screen, 暂时不明白redis 中关于守护线程的问题. 解决方案 就是普通命令方式启动daemonize,它也会是守护进程,也就是达到scree

java并发编程学习: 守护线程(Daemon Thread)

在正式理解这个概念前,先把 守护线程 与 守护进程 这二个极其相似的说法区分开,守护进程通常是为了防止某些应用因各种意外原因退出,而在后台独立运行的系统服务或应用程序. 比如:我们开发了一个邮件发送程序,一直不停的监视队列池,发现有待发送的邮件,就将其发送出去.如果这个程序挂了(或被人误操作关了),邮件就不发出去了,为了防止这种情况,再开发一个类似windows 系统服务的应用,常驻后台,监制这个邮件发送程序是否在运行,如果没运行,则自动将其启动.   而我们今天说的java中的守护线程(Dae

Java守护线程概述

Java的线程分为两种:User Thread(用户线程).DaemonThread(守护线程). 只要当前JVM实例中尚存任何一个非守护线程没有结束,守护线程就全部工作:只有当最后一个非守护线程结束是,守护线程随着JVM一同结束工作,Daemon作用是为其他线程提供便利服务,守护线程最典型的应用就是GC(垃圾回收器),他就是一个很称职的守护者. User和Daemon两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下Daemon Thre

Java并发编程示例(七):守护线程的创建和运行_java

Java有一种特殊线程,守护线程,这种线程优先级特别低,只有在同一程序中的其他线程不执行时才会执行. 由于守护线程拥有这些特性,所以,一般用为为程序中的普通线程(也称为用户线程)提供服务.它们一般会有一个无限循环,或用于等待请求服务,或用于执行任务等.它们不可以做任何重要的工作,因为我们不确定他们什么时才能分配到CPU运行时间,而且当没有其他线程执行时,它们就会自动终止.这类线程的一个典型应用就是Java的垃圾回收. 在本节示例中,我们将创建两个线程,一个是普通线程,向队列中写入事件:另外一个是