面试又被问线程池原理?教你如何反击,2024年最新java面试技巧和注意事项

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

这里大概总结下execute方法的执行流程,其实大家看源码方法注释是一样很好的学习方法

  • 首先判断当前线程数量是不是比核心线程数量少,如果是,直接创建核心线程执行任务,否则走第二步

  • 如果当前线程数量等于核心线程数量了,那么就任务排期,将任务放进任务队列,放入成功后,再次check线程池状态,这里说明一下,在多线程的环境下,ctl.get()这个方法并不是一个原子操作,如果加入队列后,线程池状态改变了,不是RUNNING状态,那么这个任务将永远不会被执行,所以需要再次check,如果不是RUNNING状态,移除任务并拒绝任务,如果是RUNNING状态并且当前没有线程,则直接创建线程

  • 走到这一步前提就是第二步中的添加队列失败了,也就是任务队列满了,那么这个时候就考虑到创建非核心线程去执行任务,如果添加非核心线程也失败,那就直接拒绝

这里注意一点,当核心线程满的时候,并不会去直接创建非核心线程去执行任务,而是先放进任务队列,可以理解为需求任务首先是需要让内部核心员工去完成的,任务队列的优先级是高于非核心员工的,addWorker(),这里的传进去的boolean值,就代表着创建核心线程或者非核心线程

reject()

final void reject(Runnable command) {

handler.rejectedExecution(command, this);

}

拒绝任务很简单,reject方法会调用handler的rejectedExecution(command,this)方法,handler是RejectedExecutionHandler接口,默认实现是AbortPolicy,下面是AbortPolicy的实现:

public static class AbortPolicy implements RejectedExecutionHandler {

public AbortPolicy() { }

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

throw new RejectedExecutionException("Task " + r.toString() +

" rejected from " +

e.toString());

}

}

可以看到默认策略是直接抛出异常的,这只是默认使用的策略,可以通过实现接口实现自己的逻辑。

addWorker()

private boolean addWorker(Runnable firstTask, boolean core) {

retry:

for (;😉 {

int c = ctl.get();

int rs = runStateOf©;

// 这里return false的情况有以下几种

//1.当前状态是stop及以上 2.当前是SHUTDOWN状态,但是firstTask不为空

//3.当前是SHUTDOWN状态,但是队列中为空

//从第一节我们知道,SHUTDOWN状态是不执行进来的任务的,但是会继续执行队列中的任务

if (rs >= SHUTDOWN &&

! (rs == SHUTDOWN &&

firstTask == null &&

! workQueue.isEmpty()))

return false;

for (;😉 {

int wc = workerCountOf©;

if (wc >= CAPACITY ||

wc >= (core ? corePoolSize : maximumPoolSize))

return false;

if (compareAndIncrementWorkerCount©)

break retry;

c = ctl.get(); // Re-read ctl

if (runStateOf© != rs)

continue retry;

// else CAS failed due to workerCount change; retry inner loop

}

}

boolean workerStarted = false;

boolean workerAdded = false;

Worker w = null;

try {

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) {

t.start();

workerStarted = true;

}

}

} finally {

if (! workerStarted)

addWorkerFailed(w);

}

return workerStarted;

}

这里就主要流程分析下

  • 2层循环,外部循环查询线程池状态,如果当前是stop及之上的状态,直接return,如果是SHUTDOWN状态,并且firstTask不为空或者队列中是空的,直接return

  • 内部循环查询线程数量,通过传递进来的boolean值,分别和核心线程以及最大线程数量进行对比,如果成立,worker数量+1,并且跳出循环。

  • 跳出循环就是实际执行任务了,Worker就将工作线程和任务封装到了自己内部,我们可以将Worker看成就是一个工作线程,至于Worker是如何执行任务和从阻塞队列中取任务

Worker()

private final class Worker

extends AbstractQueuedSynchronizer

implements Runnable

{

/** Thread this worker is running in. Null if factory fails. */

final Thread thread;

/** Initial task to run. Possibly null. */

Runnable firstTask;

/** Per-thread task counter */

volatile long completedTasks;

Worker(Runnable firstTask) {

setState(-1); // inhibit interrupts until runWorker

this.firstTask = firstTask;

this.thread = getThreadFactory().newThread(this);

}

public void run() {

runWorker(this);

}

}

可以看到,Worker内部维护,一个线程变量以及任务变量,启动一个 Worker对象中包含的线程 thread, 就相当于要执行 runWorker()方法, 并将该 Worker对象作为该方法的参数.

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 {

//task不为空,执行当前任务,任务执行完后将task置位空,getTask方法接着不断从队列中取任务

while (task != null || (task = getTask()) != null) {

w.lock();

//再次check线程池状态,如果是stop状态,直接interrupt()中断任务

if ((runStateAtLeast(ctl.get(), STOP) ||

(Thread.interrupted() &&

runStateAtLeast(ctl.get(), STOP))) &&

!wt.isInterrupted())

wt.interrupt();

try {

beforeExecute(wt, task);

Throwable thrown = null;

try {

//执行任务

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

}

}

通过while循环不断的调用getTask方法,获取任务task并进行执行,如果任务都执行完,跳出循环,线程结束并减少当前线程数量。

getTask()

private Runnable getTask() {

boolean timedOut = false; // Did the last poll() time out?

for (;😉 {

int c = ctl.get();

int rs = runStateOf©;

// Check if queue empty only if necessary.

if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {

decrementWorkerCount();

return null;

}

int wc = workerCountOf©;

// Are workers subject to culling?

boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

if ((wc > maximumPoolSize || (timed && timedOut))

&& (wc > 1 || workQueue.isEmpty())) {

if (compareAndDecrementWorkerCount©)

return null;

continue;

}

try {

Runnable r = timed ?

workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :

workQueue.take();

if (r != null)

return r;

timedOut = true;

} catch (InterruptedException retry) {

timedOut = false;

总结

其他的内容都可以按照路线图里面整理出来的知识点逐一去熟悉,学习,消化,不建议你去看书学习,最好是多看一些视频,把不懂地方反复看,学习了一节视频内容第二天一定要去复习,并总结成思维导图,形成树状知识网络结构,方便日后复习。

这里还有一份很不错的《Java基础核心总结笔记》,特意跟大家分享出来

目录:

部分内容截图:

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
形成树状知识网络结构,方便日后复习。

这里还有一份很不错的《Java基础核心总结笔记》,特意跟大家分享出来

目录:

[外链图片转存中…(img-57AfUUCL-1713558284672)]

部分内容截图:

[外链图片转存中…(img-3nQX0IUm-1713558284673)]

[外链图片转存中…(img-77G9dKpn-1713558284673)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-efrDTIJP-1713558284673)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值