zoukankan      html  css  js  c++  java
  • 多线程之join方法

    一.前言:

           在很多情况下,我们都是通过主线程创建并启动子线程的,如果子线程中需要耗费大量的时间计算的话,主线程往往会比子线程先结束,这个时候就会导致有时候主线程想获取子线程计算之后的结果,但是却获取不到。这个时候,我们就可以通过join方法来解决这个问题。

    二.join方法的作用:

    join方法的作用是使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。方法join具有使线程排队运行的作用,有些类似同步的运行效果。

    下面看一个例子:

    public class MyThread extends Thread{
        @Override
        public void run() {
            int sencondValue = (int)(Math.random()*1000);
            System.out.println(sencondValue);
            try {
                Thread.sleep(sencondValue);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public class Run {
        public static void main(String[] args) throws InterruptedException {
            MyThread myThread = new MyThread();
            myThread.start();
            myThread.join();
            System.out.println("当对象myThread执行完毕后再执行");
        }
    }

    运行结果:join的意思是使得放弃当前线程的执行,并返回对应的线程,例如上面代码的意思就是:程序在main线程中调用myThread线程的join方法,则main线程放弃cpu控制权,并返回myThread线程继续执行直到线程myThread执行完毕。所以结果是线程myThread执行完后,才到主线程执行,相当于在main线程中同步线程myThreadmyThread执行完了,main线程才有执行的机会 此外,join方法和interrupt方法相遇的时候会抛出异常。

    此外,还有join(long millis)方法,指定要等待多长时间。

    三.join的实现原理:

    查看join方法源码:

    /**
         * Waits for this thread to die.
         *
         * <p> An invocation of this method behaves in exactly the same
         * way as the invocation
         *
         * <blockquote>
         * {@linkplain #join(long) join}{@code (0)}
         * </blockquote>
         *
         * @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 void join() throws InterruptedException {
            join(0);
        }
    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方法实际上是通过调用wait方法, 来实现同步的效果的。例如,A线程中调用了B线程的join方法,则相当于A线程调用了B线程的wait方法,在调用了B线程的wait方法后,A线程就会进入阻塞状态,因为它相当于放弃了CPU的使用权。需要注意的是,jdk规定,join(0)的意思不是A线程等待B线程0秒,而是A线程等待B线程无限时间,直到B线程执行完毕,即join(0)等价于join()。

    四.join方法和synchronized、sleep方法的区别:

    1.从上面的源码我们可以看出,join(long millis)是通过在内部使用wait(long millis)方法来实现的,所有它其实是具有释放锁的特点的,在执行完;而sleep(long millis)是不释放锁的,也就是如果有Synchronized同步块,其他线程仍然不能访问共享数据。注意该方法要捕获异常。

    2.join在内部使用wait()方法进行等待,而synchronized关键字使用的是“对象监控器”原理做同步,具体可以看这个synchronized原理

    参考:https://www.2cto.com/kf/201608/543154.html

               https://www.cnblogs.com/lcplcpjava/p/6896904.html

  • 相关阅读:
    vue中select设置默认选中
    验证码
    JS图片src转义
    int main(int argc, char** argv) 以及CommandLineParser
    Visual Studio2013 配置opencv3.3.0 x64系统
    ubuntu16.04 下安装 visual studio code 以及利用 g++ 运行 c++程序
    第三次作业
    第二次作业
    作业一
    第四次作业
  • 原文地址:https://www.cnblogs.com/baichendongyang/p/13235522.html
Copyright © 2011-2022 走看看