Thread的join方法实际上就是调用某个线程(B线程,被调用者)的join方法的线程(A线程,调用者),在执行完这个调用方法后被阻塞,必须等待被调用线程(B线程)执行完后才能继续执行: 

class CustomThread1 extends Thread {
	public CustomThread1() {
		super("[CustomThread1] Thread");
	};

	public void run() {
		String threadName = Thread.currentThread().getName();
		System.out.println(threadName + " start.");
		try {
			for (int i = 0; i < 5; i++) {
				System.out.println(threadName + " loop at " + i);
				Thread.sleep(1000);
			}
			System.out.println(threadName + " end.");
		} catch (Exception e) {
			System.out.println("Exception from " + threadName + ".run");
		}
	}
}

class CustomThread extends Thread {
	CustomThread1 t1;

	public CustomThread(CustomThread1 t1) {
		super("[CustomThread] Thread");
		this.t1 = t1;
	}

	public void run() {
		String threadName = Thread.currentThread().getName();
		System.out.println(threadName + " start.");
		try {
			t1.join();
			System.out.println(threadName + " end.");
		} catch (Exception e) {
			System.out.println("Exception from " + threadName + ".run");
		}
	}
}

public class JoinThread {
	public static void main(String[] args) {
		String threadName = Thread.currentThread().getName();
		System.out.println(threadName + " start.");
		CustomThread1 tt = new CustomThread1();
		CustomThread t = new CustomThread(tt);
		try {
			tt.start();
			Thread.sleep(2000);
			t.start();
			t.join();// 在代碼2里,將此處注釋掉
			System.out.println("JoinThread IS /NO take action!");
		} catch (Exception e) {
			System.out.println("Exception from main");
		}
		System.out.println(threadName + " end!");
	}
}