zoukankan      html  css  js  c++  java
  • java多线程之守护线程以及Join方法

    版权声明:本文出自汪磊的博客,转载请务必注明出处。

    一、守护线程概述及示例

    守护线程就是为其它线程提供"守护"作用,说白了就是为其它线程服务的,比如GC线程。

    java程序中线程分两种:用户线程与守护线程,用户线程就是我们平常编写的一个个子线程,比如负责下载的线程,上传数据的线程等。如果一个线程调用了setDaemon(true)方法则变成了守护线程,两种线程本质上没什么区别,但是当一个工程中所有用户线程都执行完了,那么守护线程就没什么服务对象了,此时虚拟机退出,守护线程被销毁。

    下面通过一个小Demo示例。编写DaemonThread类,如下:

     1 public class DaemonThread extends Thread {
     2 
     3     @Override
     4     public void run() {
     5         
     6         while(true){
     7             try {
     8                 Thread.sleep(1000);
     9                 System.out.println("我是线程"+Thread.currentThread().getName()+"我正在执行");
    10             } catch (Exception e) {
    11                 //
    12                 e.printStackTrace();
    13             }
    14         }
    15     }
    16 }

    很简单,在DaemonThread的run方法中先让线程休眠一秒钟,然后打印一下信息,接下来看下main中逻辑:

     1 public static void main(String[] args) {
     2         //
     3         DaemonThread d1 = new DaemonThread();
     4         d1.setDaemon(true);
     5        d1.start();
     6         
     7         for(int i=0;i<500;i++){
     8             System.out.println("我是线程"+Thread.currentThread().getName()+"我正在执行:"+i);
     9        }
    10 }

    主要逻辑就是调用setDaemon方法将d1线程设置为守护线程,主线程中循环打印信息。运行打印如下信息:

      1 我是线程main我正在执行:0
      2 我是线程main我正在执行:1
      3 我是线程main我正在执行:2
      4 我是线程main我正在执行:3
      5 我是线程main我正在执行:4
      6 我是线程main我正在执行:5
      7 我是线程main我正在执行:6
      8 我是线程main我正在执行:7
      9 我是线程main我正在执行:8
     10 我是线程main我正在执行:9
     11 我是线程main我正在执行:10
       ....
     12 我是线程main我正在执行:96
     13 我是线程main我正在执行:97
     14 我是线程main我正在执行:98
     15 我是线程main我正在执行:99

    我们看到只有主线程中信息打印,d1守护线程没有任何信息打印出,原因也很好解释了,运行程序主线程瞬间执行完毕,此时项目中没有其余线程工作,JVM也就退出了,进而d1线程也就得不到执行就被销毁了。守护线程介绍到此为止。

    一、线程join()方法概述及示例

    我所理解的join()的方法主要作用就是"等待"的作用,什么意思呢?比如B线程要等A线程执行完才开始执行其逻辑,那么就可以在B线程即将开始执行其逻辑的时候调用A线程的join()方法,此时就会转到A线程逻辑执行,执行完继续回来执行B线程逻辑,记住:要想join()方法起作用,A线程此时必须是alive状态(源码中有体现)。

    直接看Demo吧.

    JoinThread1类:很简单就是打印信息

     1 public class JoinThread1 extends Thread {
     2 
     3     @Override
     4     public void run() {
     5         
     6         try {
     7             int nextInt = new Random().nextInt(5);
     8             Thread.sleep(nextInt * 1000);
     9             System.out.println("我是线程"+Thread.currentThread().getName()+"我睡了"+nextInt+"秒");
    10         } catch (InterruptedException e) {
    11             e.printStackTrace();
    12         }
    13     }
    14 }

    JoinThread2类:

     1 public class JoinThread2 extends Thread {
     2     
     3     private Thread mThread;
     4     
     5     public JoinThread2(Thread mThread) {
     6         super();
     7         this.mThread = mThread;
     8     }
     9 
    10     @Override
    11     public void run() {
    12         
    13         try {
    14           mThread.join();
    15             int nextInt = new Random().nextInt(5);
    16             Thread.sleep(nextInt * 1000);//sleep在同步的方法中是不释放对象锁的,只有同步方法执行完毕,其他线程才可以执行。
    17             System.out.println("我是线程"+Thread.currentThread().getName()+"我睡了"+nextInt+"秒");
    18             
    19         } catch (InterruptedException e) {
    20             e.printStackTrace();
    21         }
    22     }
    23 }

    初始化的时候传进来一个mThread,在run方法执行的时候首先调用传递进来的mThread的join()方法然后在执行其逻辑。

    mian方法:

     1 public static void main(String[] args) {
     2         //
     3         try {
     4             JoinThread1 join1 = new JoinThread1();
     5             join1.start();
     6             JoinThread2 join2 = new JoinThread2(join1);
     7             join2.start();
     8             join2.join();//join底层是wait方法,会释放对象锁的
     9         } catch (InterruptedException e) {
    10             e.printStackTrace();
    11         }
    12         System.out.println("我是主线程我执行完毕了");
    13 }

    main方法中逻辑也很简单,主要是初始化线程并启动,但是我们调用了join2.join()方法,所以主线程就要等待join2线程执行完毕才继续往下执行,运行程序输出如下:

    1 我是线程Thread-0我睡了1秒
    2 我是线程Thread-1我睡了0秒
    3 我是主线程我执行完毕了

    如果你理解了上面说的打印信息顺序应该很容易理解。

    但是如果main代码改为如下输出Log是什么样的呢:

    public static void main(String[] args) {
            //
            try {
                JoinThread1 join1 = new JoinThread1();
                join1.start();
                JoinThread2 join2 = new JoinThread2(join1);
                join2.join();//join底层是wait方法,会释放对象锁的
                join2.start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("我是主线程我执行完毕了");
    }

    改为如下又是什么呢?

     1 public static void main(String[] args) {
     2         //
     3         try {
     4             JoinThread1 join1 = new JoinThread1();
     5             JoinThread2 join2 = new JoinThread2(join1);
     6             join2.start();
     7             join2.join();//join底层是wait方法,会释放对象锁的
     8             join1.start();
     9         } catch (InterruptedException e) {
    10             e.printStackTrace();
    11         }
    12         System.out.println("我是主线程我执行完毕了");
    13 }

    如果你能全部答对那么join()方法你就基本全部理解了,知识点虽小,但是也要认真理解透!!!

    本文到此为止,希望对你有帮助。

  • 相关阅读:
    java io系列23之 BufferedReader(字符缓冲输入流)
    java io系列22之 FileReader和FileWriter
    java io系列21之 InputStreamReader和OutputStreamWriter
    java io系列20之 PipedReader和PipedWriter
    java io系列19之 CharArrayWriter(字符数组输出流)
    java io系列18之 CharArrayReader(字符数组输入流)
    java io系列17之 System.out.println("hello world")原理
    java io系列16之 PrintStream(打印输出流)详解
    java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
    java io系列14之 DataInputStream(数据输入流)的认知、源码和示例
  • 原文地址:https://www.cnblogs.com/leipDao/p/8288772.html
Copyright © 2011-2022 走看看