zoukankan      html  css  js  c++  java
  • 浅析Java的Thread.join函数

    (一)join参数解析

    join(): 即join(0),主线程无限等待子进程结束,主线程方可执行。

    join(long millis):主线程需等待子进程*毫秒,主线程方可执行。

    (二)join源码

    join函数用了synchronized关键字,即为同步,线程安全。

       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");
            }
    
            if (millis == 0) {
                while (isAlive()) {
                    wait(0);
                }
            } else {
                while (isAlive()) {
                    long delay = millis - now;
                    if (delay <= 0) {
                        break;
                    }
                    wait(delay);
                    now = System.currentTimeMillis() - base;
                }
            }
        }
    

    (三)join 案例分析

    自定义线程函数,方便查看结果比较函数效果

    public class ThreadJoin extends Thread {
        public ThreadJoin(String name) {
            super(name);
        }
    
        @Override
        public void run(){
            for(int i=0;i<10;i++){
                System.out.println("i:" + i + ", name:" + this.getName());
            }
        }
    }

    【测试一】.线程无join()

    public class ThreadJoinTest {
        public static void main(String [] args)throws InterruptedException {
            ThreadJoin threadOne = new ThreadJoin("晓东");
            ThreadJoin threadTwo = new ThreadJoin("小明");
            System.out.println("---Test start---");
            threadOne.start();
            threadTwo.start();
            System.out.println("---Test end---");
        }
    }
    

    运行结果:

    ---Test start---
    ---Test end---
    i:0, name:晓东
    i:0, name:小明
    i:1, name:小明
    i:2, name:小明
    i:1, name:晓东
    i:3, name:小明
    i:4, name:小明
    i:2, name:晓东
    i:5, name:小明
    i:6, name:小明
    i:3, name:晓东
    i:7, name:小明
    i:4, name:晓东
    i:5, name:晓东
    i:6, name:晓东
    i:7, name:晓东
    i:8, name:晓东
    i:9, name:晓东
    i:8, name:小明
    i:9, name:小明

    总结:Main线程先执行,然后threadOne和threadTwo子进程随机执行,当谁抢占CPU资源的时候,即执行System.out.println("i:" + i + ", name:" + this.getName())。由于线程抢占资源

    不确定性,所以两个子进程的执行顺序不一,重复运行的结果也不一样。

    【测试二】.线程join()

    public class ThreadJoinTest {
        public static void main(String [] args)throws InterruptedException {
            ThreadJoin threadOne = new ThreadJoin("晓东");
            ThreadJoin threadTwo = new ThreadJoin("小明");
            System.out.println("---Test start---");
            threadOne.start();
            threadTwo.start();
            threadOne.join();
            threadTwo.join();
            System.out.println("---Test end---");
        }
    }
    

      运行结果:

    ---Test start---
    i:0, name:晓东
    i:0, name:小明
    i:1, name:小明
    i:2, name:小明
    i:1, name:晓东
    i:3, name:小明
    i:2, name:晓东
    i:3, name:晓东
    i:4, name:小明
    i:4, name:晓东
    i:5, name:小明
    i:5, name:晓东
    i:6, name:小明
    i:6, name:晓东
    i:7, name:晓东
    i:8, name:晓东
    i:9, name:晓东
    i:7, name:小明
    i:8, name:小明
    i:9, name:小明
    ---Test end---
    

     总结:可以看出Main主进程先执行start,然后执行两个子进程,最后执行Main主进程的end。所以这个可以看出,主线程必须等到子进程都结束后,才执行。同样子进程的运行顺序也是不一样的。

    这里需要注意下,子进程的join()是让正在运行的父亲进程(即Main主进程)进入等待,而不是new thread的子进程进入等待。即让正在运行的进程进入等待。

    【测试三】.线程join()在子进程开始运行之前和开始运行之后是否有差异

    public class ThreadJoinTest {
        public static void main(String [] args)throws InterruptedException {
            ThreadJoin threadOne = new ThreadJoin("晓东");
            ThreadJoin threadTwo = new ThreadJoin("小明");
    
            System.out.println("---Test start---");
            threadOne.join();
            threadTwo.join();
            threadOne.start();
            threadTwo.start();
            System.out.println("---Test end---");
        }
    }
    

     运行结果:

    ---Test start---
    ---Test end---
    i:0, name:晓东
    i:0, name:小明
    i:1, name:晓东
    i:1, name:小明
    i:2, name:晓东
    i:3, name:晓东
    i:2, name:小明
    i:4, name:晓东
    i:3, name:小明
    i:4, name:小明
    i:5, name:小明
    i:5, name:晓东
    i:6, name:小明
    i:6, name:晓东
    i:7, name:小明
    i:7, name:晓东
    i:8, name:小明
    i:8, name:晓东
    i:9, name:小明
    i:9, name:晓东
    

     总结:可以看出运行结果和无join()的【测试一】是一样的。所以start()前执行join()无效,类似于只执行start()

    【测试四】join()和join(**)区别

    代码一:

    public class ThreadJoin extends Thread {
        public ThreadJoin(String name) {
            super(name);
        }
    
        @Override
        public void run(){
            for(int i=0;i<100;i++){
                System.out.println("i:" + i + ", name:" + this.getName());
            }
        }
    }
    public class ThreadJoinTest {
        public static void main(String [] args)throws InterruptedException {
            ThreadJoin threadOne = new ThreadJoin("晓东");
            ThreadJoin threadTwo = new ThreadJoin("小明");
    
            System.out.println("---Test start---");
            threadOne.start();
            threadTwo.start();
            threadOne.join(0);
            System.out.println("---Test end---");
        }
    }
    

     代码二:

    public class ThreadJoin extends Thread {
        public ThreadJoin(String name) {
            super(name);
        }
    
        @Override
        public void run(){
            for(int i=0;i<100;i++){
                System.out.println("i:" + i + ", name:" + this.getName());
            }
        }
    }
    public class ThreadJoinTest {
        public static void main(String [] args)throws InterruptedException {
            ThreadJoin threadOne = new ThreadJoin("晓东");
            ThreadJoin threadTwo = new ThreadJoin("小明");
    
            System.out.println("---Test start---");
            threadOne.start();
            threadTwo.start();
            threadOne.join(1);
            System.out.println("---Test end---");
        }
    }

    代码二运行结果:

    ---Test start---
    i:0, name:晓东
    i:0, name:小明
    i:1, name:小明
    i:2, name:小明
    i:1, name:晓东
    i:3, name:小明
    i:2, name:晓东
    i:4, name:小明
    i:3, name:晓东
    i:5, name:小明
    i:4, name:晓东
    i:6, name:小明
    i:5, name:晓东
    i:7, name:小明
    i:8, name:小明
    i:9, name:小明
    i:10, name:小明
    i:6, name:晓东
    i:11, name:小明
    i:7, name:晓东
    i:8, name:晓东
    i:9, name:晓东
    i:10, name:晓东
    i:11, name:晓东
    i:12, name:晓东
    i:12, name:小明
    i:13, name:晓东
    i:13, name:小明
    i:14, name:小明
    i:15, name:小明
    ---Test end---
    i:14, name:晓东
    i:16, name:小明
    i:15, name:晓东
    i:17, name:小明
    i:16, name:晓东
    i:18, name:小明
    
    ...

    运行结果:不一样。

    代码一:先执行主线程start,然后执行两个子线程,最后执行主线程end。

    代码二:先执行主线程start,然后执行两个子线程部分,主线程睡眠1毫秒唤醒后,执行主线程end,再执行两个子线程剩下部分。

    总结:join()无限等待子进程结束, join(*毫秒)主线程只是等待子进程*毫秒。

  • 相关阅读:
    联表查询更新
    SQLServer 中多行数据合并成一行数据(一个字段)
    换行和回车的区别
    SQL语句中使用回车换行符
    g2o使用总结
    求导总结
    ubuntu14.04 升级gcc
    如何入门SLAM
    imu和canmera标定
    使用velodyne16线激光雷达跑loam-velodyne------包括激光雷达和imu的标定
  • 原文地址:https://www.cnblogs.com/wendy777/p/9483467.html
Copyright © 2011-2022 走看看