Thread and AbstractQueuedSynchronizer

Thread中join实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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对象被锁住则会等待其被释放。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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();
        }
    }
}
1
2
3
4
5
6
7
8
start join at Sun Jun 30 18:40:08 CST 2019
Leon begins: Sun Jun 30 18:40:08 CST 2019
getObjectLock at Sun Jun 30 18:40:08 CST 2019
ReleaseObjectLock at Sun Jun 30 18:40:10 CST 2019
stop join at Sun Jun 30 18:40:11 CST 2019
getObjectLock again at Sun Jun 30 18:40:11 CST 2019
ReleaseObjectLock again at Sun Jun 30 18:40:13 CST 2019
Leon has finished: Sun Jun 30 18:40:18 CST 2019

Thread详解 Java并发之AQS详解