前言
今日鼠鼠我啊,约到一个面试了。虽然是个小公司但是投大公司别人也不理双非啊。QAQ
面试题如下
- ArrayList和LinkedList底层实现区别 (对于阅读过源码的我来说没什么毛病)
- JVM堆的内存结构、对象晋升(对于能进行JVM调优的我来说不是问题,今天早上还模拟OOM排查问题来着没想到这么简单)
- java多线程你是怎么使用的(线程池)
- 线程池的参数如何进行选取(这里说得不太好 cpu密集型和io密集型来讨论)
- Spring的生命周期 用了那些设计模式 AOP的实现原理 (阅读过一小部分的spring源码直接拿捏)
- Redis你用到什么地方(分布式锁和热点数据缓存)
- 分布式锁的实现(太常规了)
- 你知道哪些Mysql的存储引擎(随便说说了 提到innodb和mysia就行)
- innodb索引数据结构(B+)
- 为什么使用B+(对比B树的优势 最大的就是顺序IO)
- innodb的事务隔离级别(我深入学习过这块 准备了MVCC机制呢不过他没问)
- 项目部分
1. 手写简易线程池代码
public class MoXiuThreadPool implements Executor {
//目前的线程池内任务数量
private final AtomicInteger ctl = new AtomicInteger(0);
//核心线程数
private volatile int corePoolSize;
//最大线程数
private volatile int maximumPoolSize;
//超过核心线程数后会加入这里
private final BlockingQueue<Runnable> workQueue;
public MoXiuThreadPool(int corePoolSize, int maximumPoolSize, BlockingQueue<Runnable> workQueue) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
}
@Override
public void execute(Runnable command) {
//获取当前任务数量
int c = ctl.get();
//如果小于核心线程数那么直接执行就好
if (c < corePoolSize) {
if (!addWorker(command)) {
reject();
}
return;
}
//大于和核心线程数得入队
if (!workQueue.offer(command)) {
//入队失败的话再试一下是否有任务空缺
if (!addWorker(command)) {
//失败策略
reject();
}
}
}
private void reject() {
throw new RuntimeException("执行拒绝策略");
}
//执行线程
private boolean addWorker(Runnable command) {
if (ctl.get() >= maximumPoolSize) {
return false;
}
Worker worker = new Worker(command);
worker.thread.start();
ctl.incrementAndGet();
return true;
}
private final class Worker implements Runnable {
Thread thread;
Runnable firstTask;
public Worker(Runnable runnable) {
thread = new Thread(this);
this.firstTask = runnable;
}
@Override
public void run() {
Runnable task = firstTask;
try {
//循环去执行任务
while (task != null || (task = getTask()) != null) {
task.run();
if (ctl.get() > maximumPoolSize) {
break;
}
task = null;
}
}finally {
ctl.decrementAndGet();
}
}
//从队列中去拿
private Runnable getTask() {
for (; ; ) {
try {
return workQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
以上实现了一个简单的线程池大家可以去跑是没问题的逻辑简单
2. JDK线程池详解
提交任务代码
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//拿到当前任务数
int c = ctl.get();
//判断任务的数量是否小于核心线程数 这里比较烦了本来就是一个32为的in类型数字 李老师非要把前2为拿出来搞出线程池状态维护
if (workerCountOf(c) < corePoolSize) {
//执行任务
if (addWorker(command, true))
return;
c = ctl.get();
}
//当前是否为运行状态 是就入队
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);
}
现在去看核心的执行任务代码
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
//拿任务
while (task != null || (task = getTask()) != null) {
w.lock();
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);
}
}
大概就是去拿任务调用任务的run方法执行,今天中午面试没睡午觉所以学习时间不长。今天拉了,明天补回来QAQ.