• Java多线程B 线程的生命周期和状态控制


    5、守护线程

    守护线程与普通线程写法上基本么啥区别,调用线程对象的方法setDaemon(true),则可以将其设置为守护线程。

     

    守护线程使用的情况较少,但并非无用,举例来说,JVM的垃圾回收、内存管理等线程都是守护线程。还有就是在做数据库应用时候,使用的数据库连接池,连接池本身也包含着很多后台线程,监控连接个数、超时时间、状态等等。

     

    setDaemon方法的详细说明:
    public final void setDaemon(boolean on)将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。    
    该方法必须在启动线程前调用。 该方法首先调用该线程的 checkAccess 方法,且不带任何参数。这可能抛出SecurityException(在当前线程中)。   
      参数: 
        on - 如果为 true,则将该线程标记为守护线程。    
      抛出:    
        IllegalThreadStateException - 如果该线程处于活动状态。    
        SecurityException - 如果当前线程无法修改该线程。

    [java] view plaincopy

    1.       

    4.     public class Test  

    5.             public static void main(String[] args)  

    6.                     Thread t1 new MyCommon();  

    7.                     Thread t2 new Thread(new MyDaemon());  

    8.                     t2.setDaemon(true);        //设置为守护线程  

    9.       

    10.                  t2.start();  

    11.                  t1.start();  

    12.           

    13.   

    14.    

    15.  class MyCommon extends Thread  

    16.          public void run()  

    17.                  for (int 05i++)  

    18.                          System.out.println("线程1" "次执行!");  

    19.                          try  

    20.                                  Thread.sleep(7);  

    21.                          catch (InterruptedException e)  

    22.                                  e.printStackTrace();  

    23.                           

    24.                   

    25.           

    26.   

    27.    

    28.  class MyDaemon implements Runnable  

    29.          public void run()  

    30.                  for (long 09999999L; i++)  

    31.                          System.out.println("后台线程第" "次执行!");  

    32.                          try  

    33.                                  Thread.sleep(7);  

    34.                          catch (InterruptedException e)  

    35.                                  e.printStackTrace();  

    36.                           

    37.                   

    38.           

    39.   


    执行结果:

    [java] view plaincopy

    1.     后台线程第0次执行!  

    2.     线程10次执行!  

    3.     线程11次执行!  

    4.     后台线程第1次执行!  

    5.     后台线程第2次执行!  

    6.     线程12次执行!  

    7.     线程13次执行!  

    8.     后台线程第3次执行!  

    9.     线程14次执行!  

    10.  后台线程第4次执行!  

    11.  后台线程第5次执行!  

    12.  后台线程第6次执行!  

    13.  后台线程第7次执行!   

    从上面的执行结果可以看出:前台线程是保证执行完毕的,后台线程还没有执行完毕就退出了。

     

    实际上:JRE判断程序是否执行结束的标准是所有的前台执线程行完毕了,而不管后台线程的状态,因此,在使用后台县城时候一定要注意这个问题。




    守护线程的用途:

    守护线程通常用于执行一些后台作业,例如在你的应用程序运行时播放背景音乐,在文字编辑器里做自动语法检查、自动保存等功能。Java的垃圾回收也是一个守护线程。守护线

    的好处就是你不需要关心它的结束问题。例如你在你的应用程序运行的时候希望播放背景音乐,如果将这个播放背景音乐的线程设定为非守护线程,那么在用户请求退出的时候,

    不仅要退出主线程,还要通知播放背景音乐的线程退出;如果设定为守护线程则不需要了。


    6、如何结束一个线程

    Thread.stop()Thread.suspendThread.resumeRuntime.runFinalizersOnExit这些终止线程运行的方法已经被废弃了,使用它们是极端不安全的!想要安全有效的结束一个线程,可以使用下面的方法。

    1、正常执行完run方法,然后结束掉

    2、控制循环条件和判断条件的标识符来结束掉线程

    比如说run方法这样写:

    [java] view plaincopy

    1.     class MyThread extends Thread  

    2.         int i=0 

    3.         @Override  

    4.         public void run()  

    5.             while (true 

    6.                 if(i==10 

    7.                     break 

    8.                 i++;  

    9.                 System.out.println(i);  

    10.                

    11.           

    12.       

    13.   

    或者

    [java] view plaincopy

    1.     class MyThread extends Thread  

    2.         int i=0 

    3.         boolean next=true 

    4.         @Override  

    5.         public void run()  

    6.             while (next)  

    7.                 if(i==10 

    8.                     next=false 

    9.                 i++;  

    10.              System.out.println(i);  

    11.           

    12.       

    13.   


    或者

    [java] view plaincopy

    1.     class MyThread extends Thread  

    2.         int i=0 

    3.         @Override  

    4.         public void run()  

    5.             while (true 

    6.                 if(i==10 

    7.                     return 

    8.                 i++;  

    9.                 System.out.println(i);  

    10.           

    11.       

    12.   


    只要保证在一定的情况下,run方法能够执行完毕即可。而不是while(true)的无线循环。

     

    3、使用interrupt结束一个线程。

    诚然,使用第2中方法的标识符来结束一个线程,是一个不错的方法,但是如果,该线程是处于sleepwaitjoin的状态的时候,while循环就不会执行,那么我们的标识符就无用武之地了,当然也不能再通过它来结束处于这3种状态的线程了。

    可以使用interrupt这个巧妙的方式结束掉这个线程。

    我们看看sleepwaitjoin方法的声明:

    [java] view plaincopy

    1.     public final void wait() throws InterruptedException  

    [java] view plaincopy

    1.     public static native void sleep(long millis) throws InterruptedException  

    [java] view plaincopy

    1.     public final void join() throws InterruptedException  

    可以看到,这三者有一个共同点,都抛出了一个InterruptedException的异常。

    在什么时候会产生这样一个异常呢?

    每个Thread都有一个中断状状态,默认为false。可以通过Thread对象的isInterrupted()方法来判断该线程的中断状态。可以通过Thread对象的interrupt()方法将中断状态设置为true

    当一个线程处于sleepwaitjoin这三种状态之一的时候,如果此时他的中断状态为true,那么它就会抛出一个InterruptedException的异常,并将中断状态重新设置为false

    看下面的简单的例子:

    [java] view plaincopy

    1.     public class Test1  

    2.         public static void main(String[] args) throws InterruptedException  

    3.             MyThread thread=new MyThread();  

    4.             thread.start();  

    5.          

    6.      

    7.       

    8.     class MyThread extends Thread  

    9.         int i=1 

    10.      @Override  

    11.      public void run()  

    12.          while (true 

    13.              System.out.println(i);  

    14.              System.out.println(this.isInterrupted());  

    15.              try  

    16.                  System.out.println("我马上去sleep");  

    17.                  Thread.sleep(2000);  

    18.                  this.interrupt();  

    19.              catch (InterruptedException e)  

    20.                  System.out.println("异常捕获了"+this.isInterrupted());  

    21.                  return 

    22.               

    23.              i++;  

    24.           

    25.       

    26.   

    测试结果:

    [java] view plaincopy

    1.     1  

    2.     false  

    3.     我马上去sleep  

    4.     2  

    5.     true  

    6.     我马上去sleep  

    7.     异常捕获了false  

    可以看到,首先执行第一次while循环,在第一次循环中,睡眠2秒,然后将中断状态设置为true。当进入到第二次循环的时候,中断状态就是第一次设置的true,当它再次进入sleep的时候,马上就抛出了InterruptedException异常,然后被我们捕获了。然后中断状态又被重新自动设置为false了(从最后一条输出可以看出来)。


     

    所以,我们可以使用interrupt方法结束一个线程。具体使用如下:

    [java] view plaincopy

    1.     public class Test1  

    2.         public static void main(String[] args) throws InterruptedException  

    3.             MyThread thread=new MyThread();  

    4.             thread.start();  

    5.             Thread.sleep(3000);  

    6.             thread.interrupt();  

    7.          

    8.      

    9.       

    10.  class MyThread extends Thread  

    11.      int i=0 

    12.      @Override  

    13.      public void run()  

    14.          while (true 

    15.              System.out.println(i);  

    16.              try  

    17.                  Thread.sleep(1000);  

    18.              catch (InterruptedException e)  

    19.                  System.out.println("中断异常被捕获了");  

    20.                  return 

    21.               

    22.              i++;  

    23.           

    24.       

    25.   

    多测试几次,会发现一般有两种执行结果:

    [java] view plaincopy

    1.     0  

    2.     1  

    3.     2  

    4.     中断异常被捕获了  

    或者

    [java] view plaincopy

    1.     0  

    2.     1  

    3.     2  

    4.     3  

    5.     中断异常被捕获了  




    这两种结果恰恰说明了  只要一个线程的中断状态一旦为true,只要它进入sleep等状态,或者处于sleep状态,立马回抛出InterruptedException异常。

    第一种情况,是当主线程从3秒睡眠状态醒来之后,调用了子线程的interrupt方法,此时子线程正处于sleep状态,立马抛出InterruptedException异常。

    第一种情况,是当主线程从3秒睡眠状态醒来之后,调用了子线程的interrupt方法,此时子线程还没有处于sleep状态。然后再第3while循环的时候,在此进入sleep状态,立马抛出InterruptedException异常。

     

     

  • 相关阅读:
    浏览器内核中各个线程之间的关系
    Browser进程和浏览器内核(Renderer进程)的通信过程
    babel 的一些记录
    mac nvm install
    小程序云开发补充
    JavaScript 导学推荐
    网页切片
    初探响应式Web设计
    WEB ICON 的探讨
    [转载]CSS 创作指南(Beta)(css规范)
  • 原文地址:https://www.cnblogs.com/luckForever/p/7254314.html
Copyright © 2020-2023  润新知