Java多线程之join

    join是线程的一个方法,在API中,它的英文解释是Waits for this thread to die.等待此线程死亡。谁等待此线程死亡呢?不难看出,这过程中至少存在两个线程,一个调用线程的线程,一个被调用的线程。我们通过一个简单的示例来理解这句话。    

package com.doufu.thread.t01;

class ThreadA extends Thread{

	private String name;
	
	public ThreadA(String name){
		this.name = name;
	}
	
	@Override
	public void run() {
		try {
			Thread.sleep(1000);//让此线程等待1秒
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(name);
	}
	
}
public class JoinTest01 {
	public static void main(String[] args) throws InterruptedException {
		ThreadA t = new ThreadA("T1");
		t.start();
		t.join();
		System.out.println("main");
	}
}

     在上面代码中,调用线程的线程是main即主线程,被调用的线程是t。t.join()的意思即等待t的死亡(运行结束),等待t运行结束的线程就是main。所以上面的代码执行结果应该是先打印T1,再打印main。    

    通过以上代码,可以理解,在A线程中调用另外一个线程B的join方法,即让线程A进入Block状态,直到线程B运行结束。下面再看一个示例:

     只贴出了修改的部分

public class JoinTest01 {
	public static void main(String[] args) throws InterruptedException {
		ThreadA t = new ThreadA("T1");
		t.join();
		t.start();
		System.out.println("main");
	}
}

   运行结果:

    

  看这输出结果,是不是觉得不对,不是好说了,在main中调用t的join方法,会让main先挂起,直到t执行结束吗,怎么先打印main了呢?我们来看下Thread类的join源码:

    

public final void join() throws InterruptedException {
        join(0);
    }

    join(),实际上是调用另外一个join(long millis)的方法,我们再来看下join(long millis)方法   

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()方法时,线程不是活着的,则无效。以下是isAlive()的源码,注意看下方法注释  

/**
     * Tests if this thread is alive. A thread is alive if it has
     * been started and has not yet died.
     *
     * @return  <code>true</code> if this thread is alive;
     *          <code>false</code> otherwise.
     */
    public final native boolean isAlive();

   我们来看一个面试题:     

写道
现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?

    此面试题,我们可以用join来实现   

class ThreadA extends Thread{

	private String name;
	
	public ThreadA(String name){
		this.name = name;
	}
	
	@Override
	public void run() {
		try {
			Thread.sleep(1000);//让此线程等待1秒
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(name);
	}
	
}

class ThreadB extends Thread{

	private String name;
	private Thread thread;
	public ThreadB(String name,Thread thread){
		this.name = name;
		this.thread = thread;
	}
	
	@Override
	public void run() {
		try {
			thread.join();//让此线程进入Block
			Thread.sleep(1000);//让此线程等待1秒
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		System.out.println(name);
	}
}
public class JoinTest01 {
	public static void main(String[] args) throws InterruptedException {
		ThreadA t1 = new ThreadA("T1");
		ThreadB t2 = new ThreadB("T2",t1);
		ThreadB t3 = new ThreadB("T3",t2);
		
		t1.start();
		t2.start();
		t3.start();
	}
}

 运行结果:   


 

 以下更简单的实现方式:

public class JoinTest {
	
	static class JoinThread implements Runnable{
		private String name;

		public JoinThread(String name){
			this.name = name;
		}
		
		@Override
		public void run() {
			System.out.println(name);
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("结束"+name);
		}
		
	}

	public static void main(String[] args) throws Exception {
		
		for(int i=0;i<3;i++){
			Thread t = new Thread(new JoinThread("t"+i));
			t.start();
			t.join();
		}
	
		System.out.println("HAHAHA");
		
		
	}

	
}

 运行结果:


使用CountDownLatch实现

import java.util.concurrent.CountDownLatch;

public class CoutDownLatchTest {

	private static final CountDownLatch c1 = new CountDownLatch(1);
	
	private static final CountDownLatch c2 = new CountDownLatch(2);
	
	public static void main(String[] args) {
		
		Thread t1 = new Thread(){
			public void run(){
				System.out.println("结束"+1);
				c1.countDown();
				c2.countDown();
			}
		};
		
		Thread t2 = new Thread(){
			public void run(){
				try {
					c1.await();
					System.out.println("结束"+2);
					c2.countDown();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
			}
		};
		
		Thread t3 = new Thread(){
			public void run(){
				try {
					c2.await();
					System.out.println("结束"+3);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
			}
		};
		
		t3.start();
		t2.start();
		t1.start();
		System.out.println("HAHAHA");
	}

猜你喜欢

转载自h140465.iteye.com/blog/2264768
今日推荐