Thread详解
Java并发之AQS详解

Thread中join实现如下:

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

其中利用了Object的wait方法,调用的前提是已经获得join线程的锁,如果thread对象被锁住则会等待其被释放。

import core.AbstractCommonConsumer;import core.CommonUtils;import core.MagnetMonitor;import core.NamedThreadPoolExecutor;import org.apache.ibatis.io.Resources;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.lang.reflect.InvocationTargetException;import java.util.Date;import java.util.LinkedList;import java.util.List;import java.util.concurrent.*;import java.util.concurrent.locks.LockSupport;class JoinTester01 implements Runnable {    private String name;    JoinTester01(String name) {        this.name = name;    }    public void run() {        System.out.printf("%s begins: %s\n", name, new Date());        try {            TimeUnit.SECONDS.sleep(10);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.printf("%s has finished: %s\n", name, new Date());    }}class JoinTester02 implements Runnable {    Thread thread;    JoinTester02(Thread thread) {        this.thread = thread;    }    Thread getThread(){        return this.thread;    }    public void run() {        synchronized (thread) {            System.out.printf("getObjectLock at %s\n", new Date());            try {                Thread.sleep(2000);            } catch (InterruptedException ex) {                ex.printStackTrace();            }            System.out.printf("ReleaseObjectLock at %s\n", new Date());        }        try {            Thread.sleep(1000);        } catch (InterruptedException ex) {            ex.printStackTrace();        }        synchronized (thread) {            System.out.printf("getObjectLock again at %s\n", new Date());            try {                Thread.sleep(2000);            } catch (InterruptedException ex) {                ex.printStackTrace();            }            System.out.printf("ReleaseObjectLock again at %s\n", new Date());        }    }}class TestMain {    public static void main(String[] args) {        Thread thread = new Thread(new JoinTester01("Leon"));        JoinTester02 tester02 = new JoinTester02(thread);        Thread getLockThread = new Thread(tester02);        getLockThread.start();        thread.start();        try {            System.out.printf("start join at %s\n", new Date());            thread.join(1000);            System.out.printf("stop join at %s\n", new Date());        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}
start join at Sun Jun 30 18:40:08 CST 2019Leon begins: Sun Jun 30 18:40:08 CST 2019getObjectLock at Sun Jun 30 18:40:08 CST 2019ReleaseObjectLock at Sun Jun 30 18:40:10 CST 2019stop join at Sun Jun 30 18:40:11 CST 2019getObjectLock again at Sun Jun 30 18:40:11 CST 2019ReleaseObjectLock again at Sun Jun 30 18:40:13 CST 2019Leon has finished: Sun Jun 30 18:40:18 CST 2019