线程池(FutureTask)
1、任务提交
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 125 126 127 128 129 130 131 132 133 134 135 136 | // 创建线程池提交任务 ExecutorService executorService = Executors.newFixedThreadPool( 1 ); for ( int i= 0 ;i< 3 ;i++){ // 提交任务,由AbstractExecutorService#submit实现 executorService.submit(()->{ System.out.println(Thread.currentThread().getName()); }); } Thread.sleep( 500 ); executorService.shutdown(); //=========================上述逻辑执行流程代码分析=================== //AbstractExecutorService#submit,有三个重载方法 // 提交Runnable类型的任务,不带有返回值 public Future<?> submit(Runnable task) // 提交带有返回值的Runnable,其中返回值为null(要想从线程池中获取执行结果,需要提交Callable类型任务) public <T> Future<T> submit(Runnable task, T result) // 提交Callable类型的任务,自带返回结果 public <T> Future<T> submit(Callable<T> task) // 以Runnable类型任务为例 public Future<?> submit(Runnable task) { // 入口检查,防止提交null if (task == null ) throw new NullPointerException(); // 类型转换,统一将提交的任务转换成RunnableFuture,其实是转换成FutureTask(FutureTask是RunnableFuture的一种实现) RunnableFuture<Void> ftask = newTaskFor(task, null ); // 任务提交的真正入口 execute(ftask); return ftask; } //AbstractExecutorService#newTaskFor protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { return new FutureTask<T>(runnable, value); } //FutureTask#构造 public FutureTask(Runnable runnable, V result) { // 使用适配器模式,将Runnable类型任务转成Callable类型,底层依赖于RunnableAdapter this .callable = Executors.callable(runnable, result); this .state = NEW; // ensure visibility of callable } // ThreadPoolExecutor#execute public void execute(Runnable command) { if (command == null ) throw new NullPointerException(); // 获取线程池状态 int c = ctl.get(); // 线程池线程个数小于核心线程数,该情况下直接将当前任务放入线程池执行 if (workerCountOf(c) < corePoolSize) { // 条件成立,说明放入线程池成功(会启动一个新线程执行该任务) if (addWorker(command, true )) return ; c = ctl.get(); } // 执行到这,前提条件有两个 1、核心线程数已到,需要排队 2、线程池放入失败,执行入队 // 入队失败后执行在构建线程池对象设定的拒绝策略 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0 ) addWorker( null , false ); } else if (!addWorker(command, false )) reject(command); } // 添加worker(worker是线程池中之行任务的线程,循环的从队列中获取任务执行),对用的逻辑是在线程池中开启线程 private boolean addWorker(Runnable firstTask, boolean core) { // 这些是一些条件判断,直接略过 retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue empty only if necessary. if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false ; for (;;) { int wc = workerCountOf(c); if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false ; if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) continue retry; // else CAS failed due to workerCount change; retry inner loop } } boolean workerStarted = false ; boolean workerAdded = false ; Worker w = null ; try { // 将提交的任务包装成worker(FutureTask实现了RunnableFuture,RunnableFuture实现了Runnable,故可以用Runnable表示提交的任务) w = new Worker(firstTask); final Thread t = w.thread; if (t != null ) { final ReentrantLock mainLock = this .mainLock; mainLock.lock(); try { // 获取线程池运行状态 int rs = runStateOf(ctl.get()); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null )) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); workers.add(w); int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true ; } } finally { mainLock.unlock(); } if (workerAdded) { // 启动worker执行任务,worker开始运行,执行worker的run方法 t.start(); workerStarted = true ; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; } // Worker#run ,线程池中任务处理 public void run() { runWorker( this ); } |
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、流程分析图
分类:
线程池
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异