zoukankan      html  css  js  c++  java
  • 多线程:Join的理解

    多线程Join的理解

    ​ 开发中使用多线程也非常少,之前因为有一个调取两个摄像头获取每帧进行活体检测时候,有人给了思路说到Join这个关键字,我才仔细的研究了一下这个。以前理解的意思是:使用join关键字,就是相当于调用join的线程如果没有执行完毕,其他线程都处于等待状态。这就相当是把线程串起来了一样。看了很多的博客,后面理解的是:那个线程等待挂起,取决与在那个线程上面调用XX.join,并不是影响到所有的线程。

    • 代码演示(正常线程执行)
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("A" + "-" + i);
                }
            });
            Thread t2 = new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("B" + "-" + i);
                }
            });
            t1.start();
            t2.start();
        }
    console
    A-1
    B-1
    B-2
    B-3
    B-4
    B-5
    A-2
    A-3
    A-4
    A-5
    
    • 当在t2线程前面使用join
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("A" + "-" + i);
                }
            });
            Thread t2 = new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("B" + "-" + i);
                }
            });
            t1.start();
            t1.join();
            t2.start();
        }
        console
    A-1
    A-2
    A-3
    A-4
    A-5
    B-1
    B-2
    B-3
    B-4
    B-5
    

    当在t2线程前面,main线程调用了t1线程的join,所以会让main线程暂时挂起。从而需要等到t1线程死亡之后才可以唤醒main线程继续执行下去

    • 当把join放在t2线程后面
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("A" + "-" + i);
                }
            });
            Thread t2 = new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("B" + "-" + i);
                }
            });
            Thread t3 = new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("C" + "-" + i);
                }
            });
            t1.start();
            t2.start();
            t1.join();
            t3.start();
        }
    console
        A-1
    A-2
    B-1
    A-3
    B-2
    A-4
    B-3
    B-4
    B-5
    A-5
    C-1
    C-2
    C-3
    C-4
    C-5
    

    无论执行多次,都可证实一点,在main线程中调用xx.join的时候挂起的是main线程,但是挂起main线程之前的执行的线程不受影响。

    Join的源码

        public final synchronized void join(long millis)
        throws InterruptedException {
            long base = System.currentTimeMillis();
            long now = 0;
    		//执行时间必须为正数
            if (millis < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
    		//执行时间为0或者缺省情况
            if (millis == 0) {
                //判断线程是否处于活动状态
                while (isAlive()) {
                    //调用线程的wait方法
                    wait(0);
                }
            } else {
                //判断线程是否处于活动状态
                while (isAlive()) {
                    long delay = millis - now;
                    if (delay <= 0) {
                        break;
                    }
                    //调用线程的wait方法
                    wait(delay);
                    now = System.currentTimeMillis() - base;
               }
            }
        }
    

    wait()的作用是让当前线程去等待。wait方法是object类中的方法,调用该方法是让获得当前对象锁的线程等待,而在t1.join()时,是在主线程中进行调用了,主线程获得join方法上的对象锁。

    isAlive()这个方法调用的是t1从Thread类中继承的native方法,是一种普通的方法调用,所以它判断的是t1线程是否还存活。

  • 相关阅读:
    【LA3461】Leonardo的笔记本
    【洛谷P3708】Koishi的数学题
    【Uva11762】Race to 1
    【uva11421】玩纸牌
    【反演复习计划】【51nod1594】Gcd and Phi
    【乱入】Uva11021麻球繁衍
    【反演复习计划】【bzoj4407】于神之怒加强版
    BZOJ3293: [Cqoi2011]分金币
    BZOJ2400: Spoj 839 Optimal Marks
    BZOJ1391: [Ceoi2008]order
  • 原文地址:https://www.cnblogs.com/yangk1996/p/12679855.html
Copyright © 2011-2022 走看看