线程池面试题总结
1 submit和execute有啥不同
submit如果传入的任务是Runnable,会将Runnable包装成Callable,且返回值固定式null,并最终调用execute
public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; }
2 FutureTask 说说他的get方法
任务状态主要有一下几种
private volatile int state; private static final int NEW = 0; private static final int COMPLETING = 1; private static final int NORMAL = 2; private static final int EXCEPTIONAL = 3;
get方法首先是支持多线程的,也就是说可以有多个线程都要获取这个执行结果
如果此时state值不是NORMAL说明执行还没有完成,此时会将线程包装成WaitNode加入到阻塞队列,并将执行get方法的线程挂起。
当执行完成后会自动的唤醒
public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { 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; setException(ex); } if (ran) set(result);
set方法就会唤醒的
3 线程池的参数
1 coreSize 2 maxSize 3 keeplive时间 4 时间的单位 5 blockingqueue 6 threadFactory 7 拒绝策略
4 这几个参数的意义
Worker(Runnable firstTask) { setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this);//this说明Worker就是一个Runnable }
对线程池提交任务,没达到coreSize之前,会一直addWorker,如果成功add了,在addWorker方法内就会执行Thread.start,执行的逻辑正好是Worker的run方法
达到了coreSize之后,尝试往阻塞队列里添加任务
如何阻塞队列满了,看maxSize是否大于coreSize,如果MaxSize大于coreSize,继续增加worker
5 maxSize小于coreSize会怎样
if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException();
6 线程池的五个状态
1 RUNNING
2 SHUTDOWN
3 STOP
4 TIDYING 当最后一个线程退出会把状态赋值这个
5 TERMINATED terminate方法有子类实现 默认啥都不干
7 worker继承了AQS,为什么要实现独占锁
tryLock拿到锁,说明worker处于忙的状态
这个独占锁是不可重入的,所以不能直接用ReentrantLock
8 worker在执行中如果有某个任务中断了当前线程怎么办
while (task != null || (task = getTask()) != null) { w.lock(); // If pool is stopping, ensure thread is interrupted; // if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt();//清除中断