zoukankan      html  css  js  c++  java
  • Java多线程10:join()方法

    一、前言

      通过一个简单的例子引入join()方法

    public class Thread01 extends Thread{
    
        @Override
        public void run() {
            for(int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + "=" + i);
            }
    
        }
    }

      main线程中起两个线程

    public class Test {
        public static void main(String[] args) throws InterruptedException {
            Thread01 thread01 = new Thread01();
            Thread01 thread02 = new Thread01();
            thread01.start();
            thread02.start();
        }
    }

      结果:

    Thread-1=0
    Thread-0=0
    Thread-0=1
    Thread-0=2
    Thread-1=1
    Thread-0=3
    Thread-1=2
    Thread-0=4
    Thread-1=3
    Thread-1=4

      说明:可以看到,thread01和thread02并发执行,没有先后顺序,现在在thread01.start()之后加入join()方法

    public class Test {
        public static void main(String[] args) throws InterruptedException {
            Thread01 thread01 = new Thread01();
            Thread01 thread02 = new Thread01();
            thread01.start();
            thread01.join();
            System.out.println("main thread after join");
            thread02.start();
        }
    }

      其他不变,看一下结果:

    Thread-0=0
    Thread-0=1
    Thread-0=2
    Thread-0=3
    Thread-0=4
    main thread after join
    Thread-1=0
    Thread-1=1
    Thread-1=2
    Thread-1=3
    Thread-1=4

      说明:可以看到,thread01在调用join()后,会优先执行,等它执行完了,才会执行thread02。在分析main线程中的执行过程之前,先看一下join()方法的源码。

    二、join()/join(long millis)

    /**
         * 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);
        }

      join()方法调用了join(long millis)方法,注意下面这个注释:意思是最多等待几ms线程(比如thread01)结束,但若是在指定的时间内没有结束,那么调用该方法的线程(calling thread 比如main)会被唤醒,和thread01并发执行。

    Waits at most {@code millis} milliseconds for this thread to die
    /**
         * 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;
                }
            }
        }

      join(long millis)是同步方法,该方法是通过循环判断线程的isAlive的值(调用join方法的线程)来调用wait方法。当有线程执行完了,notifyAll方法会被调用,使其他处于等待的线程开始执行。

      分析一下main方法中的执行过程。在main线程中,首先thread01依次调用start()-->join()-->join(0)方法,因为join(long millis)是同步方法,main线程会去获取与thread01对象关联的monitor的所有权(The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref),thread01对象关联的monitor还没有被别的线程所有,所以main线程进入该同步方法,传入的参数millis为0,接着判断thread01线程isAlive(Tests if this thread is alive. A thread is alive if it has been started and has not yet died),为true,调用wait()方法,main线程处于等待状态,而thread01线程继续执行,当thread01线程执行完毕,join(long millis)方法结束,notifyAll()方法会被调用,main线程被唤醒,继续执行,打印出"main thread after join"语句,执行thread02线程。

  • 相关阅读:
    搜索专题
    KMP专题
    CSU 1326: The contest(分组背包)
    强连通专题
    MST:Bad Cowtractors(POJ 2377)
    MST:Agri-Net(POJ 1258)
    ShortestPath:Layout(POJ 3169)(差分约束的应用)
    MST:Conscription(POJ 3723)
    MST:Roadblocks(POJ 3255)
    DP:Space Elevator(POJ 2392)
  • 原文地址:https://www.cnblogs.com/zfyang2429/p/10610250.html
Copyright © 2011-2022 走看看