`
coach
  • 浏览: 386703 次
  • 性别: 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中的守护线程是那些支持应用程序运行但不阻碍JVM退出的线程。正确使用守护线程可以优化资源管理,提高系统效率,并确保程序能够优雅地退出。在设计和实现多线程应用时,理解并合理利用守护线程的概念...

    JVM中的守护线程示例详解

    总结来说,守护线程在Java中扮演着重要角色,它们在后台默默工作,为用户线程提供支持,但不会影响JVM的退出。理解守护线程的工作原理对于优化Java应用性能和资源管理至关重要。正确使用守护线程可以提高程序的效率...

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

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

    java多线程总结

    当所有非守护线程结束时,程序会退出,即使守护线程仍在运行。 10. **并发工具类** Java并发包(java.util.concurrent)提供了许多高效且线程安全的工具类,如Semaphore(信号量)、CyclicBarrier(屏障)、...

    JAVA多线程总结

    【JAVA多线程总结】 Java 多线程是Java编程中的关键特性,它允许程序同时执行多个任务,提高系统的效率和响应性。本篇总结涵盖了Java多线程的基础概念、创建与启动、线程调度、同步与协作以及新特性。 **一、Java...

    Java多线程编程总结

    - 守护线程是在JVM中为其他线程提供服务的线程,当所有非守护线程结束时,JVM也会退出。 #### 八、Java线程:线程的同步-同步方法与同步块 1. **同步方法** - `synchronized` 关键字可用于修饰方法,确保同一...

    Java线程优先级和守护线程原理解析

    "Java线程优先级和守护线程原理解析" Java线程优先级和守护线程原理解析是Java多线程编程中两个重要的概念。线程优先级指的是线程执行的优先级别,守护线程是指在后台运行的线程。 一、线程优先级的介绍 Java中的...

    Java多线程编程总结.doc

    守护线程则服务于用户线程,如垃圾收集器就是守护线程,即使所有用户线程都结束,守护线程仍会继续运行,直到JVM停止。 创建Java线程主要有两种方式: 1. 扩展`java.lang.Thread`类。通过重写`run()`方法来定义线程...

    java两个线程互相守护

    线程守护(Daemon)是一种特殊类型的线程,它的主要特点是当所有非守护线程结束时,程序会自动终止,即使还有守护线程在运行。通常,后台服务或者定时任务等不直接影响程序主要功能的线程会被设置为守护线程。 在...

    ava多线程编程总结

    守护线程是一种特殊类型的线程,它不会阻止JVM的退出,只有当所有非守护线程结束时,JVM才会终止。 Java的线程API提供了丰富的控制功能,包括线程的启动、暂停、恢复、中断以及同步等。例如,可以使用start()方法...

    Java 语法总结——线程(线程)

    守护线程(Daemon Thread)是一种特殊的线程,当所有非守护线程结束后,Java虚拟机会自动停止守护线程。例如,垃圾收集器就是守护线程。通过setDaemon(true)方法可以将线程设置为守护线程。 通过以上内容,你应该对...

    corejava多线程学习总结.pdf

    - **守护线程**:Java虚拟机中存在一个特殊的守护线程——垃圾回收线程,用于自动回收不再使用的内存。虚拟机进程只有在所有非守护线程结束后才会终止。 #### 七、示例分析 考虑下面的示例代码: ```java public ...

    Java_多线程编程线程:大总结

    用户线程的结束会直接影响JVM的生命周期,而守护线程通常由系统或库管理,如垃圾回收线程。 #### 三、Java线程的创建与启动 Java提供了两种主要的方式创建线程: 1. **继承`java.lang.Thread`类**:重写`run()`...

    对python 多线程中的守护线程与join的用法详解

    Python的多线程是并发执行...总结,Python的多线程机制提供了处理并发任务的能力,守护线程和join()方法则是控制线程生命周期和同步的关键。正确理解和使用这些特性,能够帮助开发者编写出更加高效、可控的多线程程序。

Global site tag (gtag.js) - Google Analytics