线程池(FutureTask)

1、任务提交 

2、任务执行

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// ThreadPoolExecutor#runWorker 线程池中任务处理核心逻辑
final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
        // 循环从任务队列中获取任务,任务来源有两种。1、任务提交的原始任务,此时线程池未满,直接构建线程执行 2、等待队列中获取 。队列获取任务是阻塞操作,队列为空时,线程会阻塞等待任务提交
            while (task != null || (task = getTask()) != null) {
                w.lock();
                // If pool is stopping, ensure thread is interrupted;
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
               // 任务最终执行处。通过submit方法向线程池中提交的任务都是被转换成FutureTask类型,并重写了run方法。故此处执行的是FutureTask中重写的run方法
                        task.run();
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        afterExecute(task, thrown);
                    }
                } finally {
                    task = null;
                    w.completedTasks++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }
 
// FutureTask#run
public void run() {
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
     // 提交的任务,不管是Runnable还是Callable都会被转换为Callable
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
       // 标记任务是否完成
            boolean ran;
            try {
           // 调用用户自定义逻辑
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
           // 异常,使用get方法会得到该异常信息
                setException(ex);
            }
            if (ran)
          // 正常执行,结果设置
                set(result);
        }
    } finally {
        runner = null;
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}
 
// FutureTask#set正常结果设置
protected void set(V v) {
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
     // 线程池执行结果
        outcome = v;
        UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
     // 任务执行完成之后的处理,用于唤醒线程池任务还没执行完成之前调用get方法获取结果导致阻塞的线程。这些被阻塞的线程会被放入阻塞队列
        finishCompletion();
    }
}
 
// FutureTask#setException 同上,只是是异常
protected void setException(Throwable t) {
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = t;
        UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
        finishCompletion();
    }
}
// FutureTask# finishCompletion
private void finishCompletion() {
    // assert state > COMPLETING;
  // 遍历阻塞队列
    for (WaitNode q; (q = waiters) != null;) {
        if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
            for (;;) {
                Thread t = q.thread;
           // 阻塞队列中有值,表示有线程在调用get方法时被阻塞。现在结果已出,需要唤醒被阻塞的线程
                if (t != null) {
                    q.thread = null;
                    LockSupport.unpark(t);
                }
                WaitNode next = q.next;
                if (next == null)
                    break;
                q.next = null; // unlink to help gc
                q = next;
            }
            break;
        }
    }
   // 提供的扩展点。在任务执行完成之后自定义逻辑
    done();
    callable = null;        // to reduce footprint
}

3、获取结果

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
// FutureTask#get 获取向线程池提交任务的执行结果
public V get() throws InterruptedException, ExecutionException {
   // 获取当前任务执行的状态
    int s = state;
   // 条件成立表示任务正在执行中,当前获取结果线程需要放入等待队列并阻塞
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    return report(s);
}
 
// FutureTask#awaitDone等待执行结果
private int awaitDone(boolean timed, long nanos)
    throws InterruptedException {
   // get操作如果指定超时则使用,否则为0,表示不需要超时逻辑
    final long deadline = timed ? System.nanoTime() + nanos : 0L;
    WaitNode q = null;
    boolean queued = false;
    for (;;) {
     // 任务结果获取过程中,用户执行了取消逻辑,需要将该线程从阻塞队列中删除
        if (Thread.interrupted()) {
            removeWaiter(q);
            throw new InterruptedException();
        }
     // 任务执行状态
        int s = state;
     // 条件成立,表示任务执行完毕,可以获取结果,之后跳出循环
        if (s > COMPLETING) {
            if (q != null)
                q.thread = null;
            return s;
        }
     // 条件成立,出现的可能是,任务已经完成,但是还没有将执行结果赋值给outcome。这种情况下不需要阻塞
        else if (s == COMPLETING) // cannot time out yet
            Thread.yield();
       // 这种情况是第一次进入排队逻辑。需要将当前调用get方法的线程封装成WaitNode。在第二次进入时,如果任务还没有执行完成,需要 入队
        else if (q == null)
            q = new WaitNode();
        else if (!queued)
            queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                 q.next = waiters, q);
     // 下面的逻辑是park逻辑。被唤醒后表示结果已具备,获取执行结果然后跳出循环,完成取数操作
        else if (timed) {
            nanos = deadline - System.nanoTime();
            if (nanos <= 0L) {
                removeWaiter(q);
                return state;
            }
       // park当前线程(带有超时)
            LockSupport.parkNanos(this, nanos);
        }
        else
       // park当前线程
            LockSupport.park(this);
    }
}

4、流程分析图

 

posted @   多少幅度  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示