• 多线程:head first Thread.join()


    不使用Thread.join() 测试线程

    先上代码:

    /**
     * Created by Zero on 2017/8/23.
     */
    public class TestJoin implements Runnable {
        public static int a = 0;
    
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                a = a + 1;
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            TestJoin j = new TestJoin();
            Thread thread = new Thread(j);
            thread.start();
            System.out.println(a);
        }
    }

     

    以上示例会输出5吗?可能性不大,有可能永远输出为0,之前在线程池原理的那篇就提到过,线程的启动和销毁都需要时间,此处因为thread还没启动好,或者正在为它分配资源准备运行,就已经执行完输出了。

    怎样才能确保每次都能输出5呢?现在有请我们的主角join方法闪亮登场,代码如下:

    /**
     * Created by apple on 2017/8/23.
     */
    public class TestJoin implements Runnable {
        public static int a = 0;
    
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                a = a + 1;
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            TestJoin j = new TestJoin();
            Thread thread = new Thread(j);
            thread.start();
            /**
             * 测试join方法的作用,与下面的threadAgain线程作对比。
             */
            thread.join();
            System.out.println(a);
            a = 0;
            Thread threadAgain = new Thread(j);
            threadAgain.start();
            System.out.println(a);
        }
    }

     

    输出的结果将是5和0。

    Thread.join()作用

    Thread.join(),之前看资料的时候,有些人说可以理解成“将两个线程合并成一个线程”,我是觉得这样说是很不科学的,虽然这样通俗易懂,但这确实是两个不同的线程,只是在调用Thread.join()后,会先执行完Thread线程后再去执行当前线程,即上述的在主线程中执行到thread.join();后,先去执行thread,直到thread执行完后再去执行主线程。

    测试Thread.join(long millis)

    /**
     * Created by apple on 2017/8/23.
     */
    public class TestJoin implements Runnable {
        public static int a = 0;
    
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                a = a + 1;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            TestJoin j = new TestJoin();
            Thread thread = new Thread(j);
            thread.start();
            /**
             * 测试join方法的作用
             */
            thread.join(3000);
            System.out.println("thread线程结果为:"+a);
            a = 0;
            Thread threadAgain = new Thread(j);
            threadAgain.start();
            System.out.println("threadAgain线程结果为:"+a);
        }
    }

     

    输出:

    thread线程结果为:3
    threadAgain线程结果为:0

    先上一段源码再来分析:

    /**
         * Waits at most {@code millis} milliseconds for this thread to
         * die. A timeout of {@code 0} means to wait forever.
         *
         * <p> This implementation uses a loop of {@code this.wait} calls
         * conditioned on {@code this.isAlive}. As a thread terminates the
         * {@code this.notifyAll} method is invoked. It is recommended that
         * applications not use {@code wait}, {@code notify}, or
         * {@code notifyAll} on {@code Thread} instances.
         *
         * @param  millis
         *         the time to wait in milliseconds
         *
         * @throws  IllegalArgumentException
         *          if the value of {@code millis} is negative
         *
         * @throws  InterruptedException
         *          if any thread has interrupted the current thread. The
         *          <i>interrupted status</i> of the current thread is
         *          cleared when this exception is thrown.
         */
        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;
                }
            }
        }

     

    这里写图片描述

    源码爸爸说了,孩子,我给你millis这么长的时间,能不能完成任务那是你的事情了,能提前完成,咱就提前走下去,不能完成,过期不候,自己看着办吧。

    默认情况下,Thread.join()即Thread.join(0),当为0的时候,那才叫真爱呢,线程会一直等下去,知道执行结束为止,才会继续朝下执行。

    isAlive():用来测试线程是否处于活动状态,相当于 run 是否还在执行。

  • 相关阅读:
    纸壳CMS替换默认实现
    ASP.Net Core 2.2 InProcess托管的Bug:unable to open database file
    GitHub设置使用SSH Key,用TortoiseGit进行Clone仓库
    在Docker中运行纸壳CMS并配置使用MySql
    使用vs code开发纸壳CMS并启用Razor智能提示
    ASP .Net Core路由(Route)
    .Net Core在Middleware中解析RouteData
    纸壳CMS可视化建站系统搭建多语言网站
    Redis的初识
    C#/Java 动态生成电子发票
  • 原文地址:https://www.cnblogs.com/dengyungao/p/7524798.html
Copyright © 2020-2023  润新知