`
coach
  • 浏览: 382467 次
  • 性别: Icon_minigender_2
  • 来自: 印度
社区版块
存档分类
最新评论

守护线程总结

阅读更多
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)

    Daemon的作用是为其他线程的运行提供便利服务,比如垃圾回收线程就是一个很称职的守护者。User和Daemon两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下Daemon Thread存在了,虚拟机也就退出了。 因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。

    值得一提的是,守护线程并非只有虚拟机内部提供,用户在编写程序时也可以自己设置守护线程。下面的方法就是用来设置守护线程的。

    public final void setDaemon(boolean on)

    这里有几点需要注意:

    (1) thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。 
    (2) 在Daemon线程中产生的新线程也是Daemon的。 
    (3) 不要认为所有的应用都可以分配给Daemon来进行服务,比如读写操作或者计算逻辑。

       因为你不可能知道在所有的User完成之前,Daemon是否已经完成了预期的服务任务。一旦User退出了,可能大量数据还没有来得及读入或写出,计算任务也可能多次运行结果不一样。这对程序是毁灭性的。造成这个结果理由已经说过了:一旦所有User Thread离开了,虚拟机也就退出运行了。

//完成文件输出的守护线程任务
import java.io.*;   
  
class TestRunnable implements Runnable{   
    public void run(){   
               try{   
                  Thread.sleep(1000);//守护线程阻塞1秒后运行   
                  File f=new File("daemon.txt");   
                  FileOutputStream os=new FileOutputStream(f,true);   
                  os.write("daemon".getBytes());   
           }   
               catch(IOException e1){   
          e1.printStackTrace();   
               }   
               catch(InterruptedException e2){   
                  e2.printStackTrace();   
           }   
    }   
}   
public class TestDemo2{   
    public static void main(String[] args) throws InterruptedException   
    {   
        Runnable tr=new TestRunnable();   
        Thread thread=new Thread(tr);   
                thread.setDaemon(true); //设置守护线程   
        thread.start(); //开始执行分进程   
    }   
}   
//运行结果:文件daemon.txt中没有"daemon"字符串。


看到了吧,把输入输出逻辑包装进守护线程多么的可怕,字符串并没有写入指定文件。原因也很简单,直到主线程完成,守护线程仍处于1秒的阻塞状态。这个时候主线程很快就运行完了,虚拟机退出,Daemon停止服务,输出操作自然失败了。


例子2 :
public class Test {
  public static void main(String args) {
  Thread t1 = new MyCommon();
  Thread t2 = new Thread(new MyDaemon());
  t2.setDaemon(true); //设置为守护线程
  t2.start();
  t1.start();
  }
  }
  class MyCommon extends Thread {
  public void run() {
  for (int i = 0; i < 5; i++) {
  System.out.println("线程1第" + i + "次执行!");
  try {
  Thread.sleep(7);
  } catch (InterruptedException e) {
  e.printStackTrace();
  }
  }
  }
  }

class MyDaemon implements Runnable {
  public void run() {
  for (long i = 0; i < 9999999L; i++) {
  System.out.println("后台线程第" + i + "次执行!");
  try {
  Thread.sleep(7);
  } catch (InterruptedException e) {
  e.printStackTrace();
  }
  }
  }
  }


后台线程第0次执行!
  线程1第0次执行!
  线程1第1次执行!
  后台线程第1次执行!
  后台线程第2次执行!
  线程1第2次执行!
  线程1第3次执行!
  后台线程第3次执行!
  线程1第4次执行!
  后台线程第4次执行!
  后台线程第5次执行!
  后台线程第6次执行!
  后台线程第7次执行!
  Process finished with exit code 0
  从上面的执行结果可以看出:
  前台线程是保证执行完毕的,后台线程还没有执行完毕就退出了。
  实际上:JRE判断程序是否执行结束的标准是所有的前台执线程行完毕了,而不管后台线程的状态,因此,在使用后台县城时候一定要注意这个问题。

实际应用例子:在使用长连接的comet服务端推送技术中,消息推送线程设置为守护线程,服务于ChatServlet的servlet用户线程,在servlet的init启动消息线程,servlet一旦初始化后,一直存在服务器,servlet摧毁后,消息线程自动退出

容器收到一个Servlet请求,调度线程从线程池中选出一个工作者线程,将请求传递给该工作者线程,然后由该线程来执行Servlet的 service方法。当这个线程正在执行的时候,容器收到另外一个请求,调度线程同样从线程池中选出另一个工作者线程来服务新的请求,容器并不关心这个请求是否访问的是同一个Servlet.当容器同时收到对同一个Servlet的多个请求的时候,那么这个Servlet的service()方法将在多线程中并发执行。
            Servlet容器默认采用单实例多线程的方式来处理请求,这样减少产生Servlet实例的开销,提升了对请求的响应时间,对于Tomcat可以在server.xml中通过<Connector>元素设置线程池中线程的数目。
如图:



为什么要用守护线程,见Web应用程序中调度器的启动和关闭问题
  • 大小: 9.6 KB
分享到:
评论
4 楼 a123159521 2014-11-07  
菜鸟不再菜 写道
楼主很明显没有说明守护线程到底是怎么服务User线程的,以及他们之间的通信。只是讲了一些关于守护线程的注意事项!


Daemon Thread is do clear work, example: GC collection, Timout Thread collection...

Thread timeoutThread = new Thread(getAsyncTimeout(), getName() + "-AsyncTimeout");
            timeoutThread.setPriority(threadPriority);
            timeoutThread.setDaemon(true);
            timeoutThread.start();

this is tomcat source code, one request will be create new Thread and new Daemon Thread, this thread will be notify the request is timeout and call Thread to exist.
3 楼 851228082 2014-03-06  
最后一段写的很好!
2 楼 菜鸟不再菜 2013-11-26  
楼主很明显没有说明守护线程到底是怎么服务User线程的,以及他们之间的通信。只是讲了一些关于守护线程的注意事项!
1 楼 Wen_JN_86 2012-07-19  
我是初学者,不太明白守护进程有什么用,主线程可以不需要守护线程独立的运行,而且主线程退出的话守护线程也会退出,那么守护线程的作用是什么呢?

相关推荐

    java多线程编程总结

    Java线程:线程的调度-守护线程 Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 ...

    Java多线程编程总结

    Java线程:线程的调度-守护线程 Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-...

    Java 守护线程,看这篇文章就对了! ( Daemon Thread )

    守护线程使用的注意事项总结 什么是Java的守护线程( Daemon Thread )? Java 提供了两种类型的线程:守护线程 和 用户线程 用户线程 (User Thread) 是高优先级线程。JVM 会在终止之前等待任何用户线程完成其任务。 ...

    Java 线程总结

    Java线程:线程的调度-守护线程 Java线程:线程的同步-同步方法 Java线程:线程的同步-同步块 Java线程:并发协作-生产者消费者模型 Java线程:并发协作-死锁 Java线程:volatile关键字 Java线程:新特征-线程池 ...

    Java多线程核心技术讲解

    Java多线程核心技术:理解多线程、在Java中实现多线程、线程的生命周期、线程的优先级、线程的同步、线程的阻塞、守护线程、线程组、线程池、总结。

    c# 面试必备线程基础知识点

    线程的知识太多,知识点有深有浅,往深的研究会涉及操作系统、CPU、内存,往浅了说就是一些语法。没有一定的知识积累,很难把线程的知识...根据线程运行模式,可以把线程分为前台线程、后台线程和守护(Daemon)线程:

    java8源码-JavaSE-Code:JavaSE的代码练习与学习笔记总结

    只要当前JVM实例中存在任何一个非守护线程在没有结束,守护线程就在工作.守护线程的作用就是为其他的非守护线程提供便利服务 第二章:对象及变量的并发访问 只有共享的资源读写才需要同步化 方法中的变量不存在非线程...

    java8源码-concurrency:java并发总结

    守护线程 1.7 Java内存模型 1.8 可重入 1.9 偏向锁、轻量级锁、重量级锁 1.10 锁的公平性 1.11 线程组 2 多线程基本实现 2.1 多线程实现 Interface Runnable Callable Future ExecutorService Class Thread ...

    记一次和大佬的聊天总结

    gc还是属于守护线程,压测空了,可以gc缓缓 百万级并发可以尝试使用入口nginx,中台部署上百个docker去分压,再用多线程 java多线程的数量和你cpu个个数并无关系,因为java不能像go一样绑定cpu,固定计算的区域 ...

    尚观史上Linux嵌入式开发系统课程

    下面是课程列表: ├day01-01 系统介绍之缓冲区刷新.mp4 ...├day27-02 线程资源回收 线程变量创建 线程属性.mp4 ├day27-03 线程栈空间获取 线程中断.mp4 ├day28-01 线程及信号量组合同步、组合互斥.mp4

    网络编程教程,很好的一本写linux网络编程书,这是我上传的源码

     15.3.3 多进程的并发服务器和多线程的并发服务器  15.3.4 客户端进程的多线程化  本章小结 第十六章 网络售票系统的简单模拟  16.1 系统的总体设计  16.1.1 应用的说明  16.1.2 数据格式的...

    java8源码-highconcurrency:《实战Java高并发程序设计》葛一鸣、郭超着电子工业出版社2015年11月第一版书上部分代码

    介绍了thread的基本操作,volatile与synchronized的基本使用,线程组和守护线程的使用线程优先级 第三章JDK并发包: 本章开始我会重点学习在《Java多线程编程核心技术》一书中没有涉及到的线程池,并发容器等知识。 ...

    6种进程防杀方案和源码.rar

    研究了一个多月,总结网上的各种防杀方法并参考其代码,特此将各种实现方法归纳为以下6种,并将其对应源码奉上。 源码全部经过自己修改调试,部分为原创,在vs2005下调试通过,在各种windows操作系统下测试过 1. ring3...

    宋劲彬的嵌入式C语言一站式编程

    34. 终端、作业控制与守护进程 1. 终端 1.1. 终端的基本概念 1.2. 终端登录过程 1.3. 网络登录过程 2. 作业控制 2.1. Session与进程组 2.2. 与作业控制有关的信号 3. 守护进程 35. 线程 1. 线程的概念 2. 线程控制 ...

    嵌入式Linux C编程入门(第2版) PPT

    4.4.9 运算符优先级总结 131 4.4.10 arm-linux运算符 综合实例 133 本章小结 137 动手练练 137 第5章 嵌入式linux c语言基础——控制语句及函数 138 5.1 嵌入式linux c语言程序结构概述 138 5.1.1...

    Linux程序设计 第4版.haozip01

    15.3.1 因特网守护进程(xinetd/inetd) 531 15.3.2 套接字选项 533 15.4 多客户 534 15.4.1 select系统调用 537 15.4.2 多客户 540 15.5 数据报 543 15.6 小结 545 第16章 用gtk+进行gnome编程 546 16.1 x...

    Linux程序设计 第4版.haozip02

    15.3.1 因特网守护进程(xinetd/inetd) 531 15.3.2 套接字选项 533 15.4 多客户 534 15.4.1 select系统调用 537 15.4.2 多客户 540 15.5 数据报 543 15.6 小结 545 第16章 用gtk+进行gnome编程 546 16.1 x...

Global site tag (gtag.js) - Google Analytics