zoukankan      html  css  js  c++  java
  • 6.Daemon线程

    1.如下代码:

    package com.bawei.multithread;
    
    public class Recursive {
    	
    	private static int counter = 0;
    	
    	public static void main(String[] args) {
    		Thread t = new Thread(){
    			@Override
    			public void run() {
    				try {
    					//Thread-0线程
    					System.out.println(Thread.currentThread().getName()+" running");
    					Thread.sleep(100000);
    					System.out.println(Thread.currentThread().getName()+" done");
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		};
    		t.start();
    		try {
    			Thread.sleep(50000);
    			//mian线程
    			System.out.println(Thread.currentThread().getName());
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		
    	}
    }
    

      当大家运行这段代码的时候,可以通过JDK安装的bin目录下的jconsole工具来查看,当前运行的线程,如下所示:

     

    从这里大家可以看到程序当前运行的线程是main线程和Thread-0线程!

    这里可以看到当我们的main线程执行完毕之后,我们的应用程序并没有推出,这是为什么呢?这是因为此时我们的应用程序还有活跃线程Thread-0!

    如果我们对程序做一点改动,给线程Thread-0对象设置一个参数即:t.setDaemon(true);此时如果我的main线程结束之后,那么创建的main线程创建的守护线程的生命周期也就跟着结束了!代码如下所示:

    package com.bawei.multithread;
    
    public class Recursive {
    	
    	private static int counter = 0;
    	
    	public static void main(String[] args) {
    		Thread t = new Thread(){
    			@Override
    			public void run() {
    				try {
    					//Thread-0线程
    					System.out.println(Thread.currentThread().getName()+" running");
    					Thread.sleep(100000);
    					System.out.println(Thread.currentThread().getName()+" done");
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		};
    		t.setDaemon(true);
    		t.start();
    		try {
    			Thread.sleep(50000);
    			//mian线程
    			System.out.println(Thread.currentThread().getName());
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

     而且这里有一点需要特别注意:t.setDaemon(true); 一定要设置在t.start()之前,否则也会报错!

    那这个Daemon线程有什么用处呢?

    比如在我们建立网络连接的时候,例如从A到B我们建立了一个长连接,大家都知道长连接是要发心跳的,无论是每隔3秒,30秒,1分钟,这个时间是由你自己设置的,然后每隔这段时间客户端就往服务器端发一个心跳包,这样就可以知道对方的存在,就知道对方是可用的,如果不可用可能就需要重新发送连接请求!如果当前线程创建好了一个连接之后,除了利用这个连接通信之外,我还要维护一个心跳,这个心跳和业务逻辑,和通信是没关系的,这个心跳只不过是做维护的一个东西,那这个时候我把创建连接之后的这个线程开辟一个daemon线程,我创建这个daemon线程的目的就是做心跳检查(healthcheck),那这个有什么好处呢?如果我们不这么做,可能建立连接的线程已经死了,但是你的这个维护线程并不会死,必须你去通知它,或者手动关掉该维护线程,但是用stop方法关闭的时候,我们可能也是关闭不了的,因为这个方法已经被弃用了,而且此时如果你的维护线程不关闭,那么你整个应用程序(application)的进程就无法关闭,因为有活活动的线程,如果我们这里将这个维护的线程设置为通信线程的守护线程,那就很好解决了,此时一旦通信线程死掉,那维护线程自然就该挂了,所以守护线程可以帮我们做一些辅助性的东西!

    setDaemon()方法默认是设置为false的!

    我这里有两个问题,就是这里的Thread-0线程是一个守护线程,如果我在Thread-0这个线程中再开辟一个线程,然后将新开辟的线程也设置为守护线程,

    第一:当Thread-0线程关闭的时候,这个新开辟的线程会关掉么?

    1.当Thread-0不是守护线程的时候,如果Thread-0执行完毕之后,Thread-0创建的新守护线程会退出么,也就是整个应用程序会结束么?答案是会的,如下代码:

    package com.bawei.multithread;
    
    public class Recursive {
    	
    	private static int counter = 0;
    	
    	public static void main(String[] args) {
    		//新线程对象
    		Thread t = new Thread(){
    			@Override
    			public void run() {
    				//在新线程里面又创建了一个新的线程对象,
    				Thread innerThread = new Thread(){
    					@Override
    					public void run() {
    						try {
    							Thread.sleep(100*1000);
    						} catch (InterruptedException e) {
    							// TODO Auto-generated catch block
    							e.printStackTrace();
    						}
    					}
    				};
    				
    				try {
    					innerThread.setDaemon(true);
    					innerThread.start();
    					Thread.sleep(10*1000);
    					System.out.println("外层t线程休息好了");
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		};//thread-0 end!
    		t.start();
    		
    	}
    }
    

    从上面的运行代码可以看出,如果t线程结束之后,t线程创建的守护线程也会结束!

    如果我们这里进一步将t线程也设置为守护线程,当main线程结束的时候,t线程毫无疑问会退出,那么t线程创建的新守护线程会退出么?也就是整个应用程序会随着main线程的结束而结束么?答案也是会的。看如下代码演示:

    package com.bawei.multithread;
    
    public class Recursive {
    	
    	private static int counter = 0;
    	
    	public static void main(String[] args) {
    		//新线程对象
    		Thread t = new Thread(){
    			@Override
    			public void run() {
    				//在新线程里面又创建了一个新的线程对象,
    				Thread innerThread = new Thread(){
    					@Override
    					public void run() {
    						try {
    							Thread.sleep(100*1000);
    						} catch (InterruptedException e) {
    							// TODO Auto-generated catch block
    							e.printStackTrace();
    						}
    					}
    				};
    				
    				try {
    					innerThread.setDaemon(true);
    					innerThread.start();
    					Thread.sleep(10*1000);
    					System.out.println("外层t线程休息好了");
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		};//thread-0 end!
    		t.setDaemon(true);
    		t.start();
    		System.out.println("main线程结束了");
    	}
    }

    所以综上所述:只要是父线程死掉之后,守护线程都会立即死掉!整个应用程序也就结束了!

    如果我们这里将t.setDaemon设置为false,也就是默认情况,那么当main线程死掉的时候,实际上子线程就不会死掉了,因为此时的子线程不是守护线程!

    package com.bawei.multithread;
    
    public class Recursive {
    	
    	private static int counter = 0;
    	
    	public static void main(String[] args) {
    		//新线程对象
    		Thread t = new Thread(){
    			@Override
    			public void run() {
    				//在新线程里面又创建了一个新的线程对象,
    				Thread innerThread = new Thread(){
    					@Override
    					public void run() {
    						try {
    							Thread.sleep(100*1000);
    						} catch (InterruptedException e) {
    							// TODO Auto-generated catch block
    							e.printStackTrace();
    						}
    					}
    					
    				};
    				
    				try {
    					innerThread.setDaemon(true);
    					innerThread.start();
    					Thread.sleep(10*1000);
    					System.out.println("外层t线程休息好了");
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		};//thread-0 end!
    		//t.setDaemon(true);
    		t.start();
    		System.out.println("main线程结束了");
    	}
    }
    

     运行一下可以看到,如果main线程死掉,此时的t线程也不会挂掉!

    第二个问题是如果Thread-0线程执行完毕、main线程也执行完毕,那么整个应用程序(application)会结束么?

    我们这里验证一下:

  • 相关阅读:
    虚函数与动态多态
    我读苏东坡
    Linux高性能服务器编程学习-第三章思维导图笔记
    Linux高性能服务器编程学习-第二章思维导图笔记
    Linux高性能服务器编程学习-第一章思维导图笔记
    【Knockout】五、创建自定义绑定
    【Knockout】三、data-bind声明式绑定
    【Knockout】四、绑定上下文
    【Knockout】一、认识Knockout,你会爱上它
    【Knockout】二、监控属性Observables
  • 原文地址:https://www.cnblogs.com/python-machine/p/7261971.html
Copyright © 2011-2022 走看看