欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多线程之join

程序员文章站 2022-07-12 19:29:02
...

    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。    

Java多线程之join
            
    
    博客分类: Java多线程 java多线程join面试题 

    通过以上代码,可以理解,在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");
	}
}

   运行结果:

 

    
Java多线程之join
            
    
    博客分类: Java多线程 java多线程join面试题 

  看这输出结果,是不是觉得不对,不是好说了,在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();
	}
}

 运行结果:   

Java多线程之join
            
    
    博客分类: Java多线程 java多线程join面试题 
 

 以下更简单的实现方式:

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");
		
		
	}

	
}

 运行结果:

Java多线程之join
            
    
    博客分类: Java多线程 java多线程join面试题 
使用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");
	}

 

  • Java多线程之join
            
    
    博客分类: Java多线程 java多线程join面试题 
  • 大小: 10 KB
  • Java多线程之join
            
    
    博客分类: Java多线程 java多线程join面试题 
  • 大小: 6.8 KB
  • Java多线程之join
            
    
    博客分类: Java多线程 java多线程join面试题 
  • 大小: 6.6 KB
  • Java多线程之join
            
    
    博客分类: Java多线程 java多线程join面试题 
  • 大小: 7.2 KB