ThreadPoolExecutor本文主要回答:
1.我们提交一个任务时,线程池是怎么处理的?何时创建新线程来处理任务?
//debug 代码
//拒绝策略
public static void main(String[]a) throws Exception{
MyTask task = new MyTask();
ExecutorService es = new ThreadPoolExecutor(5,5,0L, TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<Runnable>(10),
Executors.defaultThreadFactory(),
new RejectedExecutionHandler(){
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(r.toString()+"is discard");
}
});
for(int i=0;i<Integer.MAX_VALUE;i++){
es.execute(task);//这里开始debug
// es.submit(task);
Thread.sleep(10);
}
}2.任务的返回值如何获取?
Executors是Executor的工具类。提供static方法 创建newFixedThreadPool,newCachedThreadPool,newScheduledThreadPool类型的线程池。
它们底层都是靠ThreadPoolExecutor实现。
看下ThreadPoolExecutor的构造函数
ThreadPoolExecutor( int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}
可以看出,线程就是在ThreadFactory中创建的。看下默认的实现类DefaultThreadFactory。
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
ScheduledThreadPoolExecutor任务要实现Runnable 或 Callabe 接口,Runnable不会返回结果,Callable可返回结果。
可通过工具类executors把Runable包装成Callable。
那么当我们submit Callable任务返回的是什么呢?答案是FutureTask对象。通过FutureTask.get()得到返回结果.
ThreadPoolExecutor 是线程池的实现类。通过其execute()执行一个任务。execute一个任务时,执行逻辑如下
(搞清:线程池到底什么时候创建线程?如何创建线程?)
//1 如果当前总线程数小于corePoolSize,则直接创建线程执行。
//2 超过corePoolSize,放入队列.
//3 队列满了,继续提交到线程池,如果到了最大线程数量,则执行//4,拒绝策略
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();//获取当前线程数目
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))//1 直接创建线程执行。
return;//成功,返回
c = ctl.get();//获取当前线程数目
}
// 如果线程池正在运行,并且添加进队列成功
if (isRunning(c) && workQueue.offer(command)) {//2
// 再次对线程池状态检查, 因为上面 addWorker 过了并且失败了,所以需要检 int recheck = ctl.get();
// 如果状态不是运行状态,且从队列删除该任务成功并尝试停止线程池 if (! isRunning(recheck) && remove(command))
reject(command); // 拒绝任务
else if (workerCountOf(recheck) == 0)// 如果当前工作线程数量为0(线程池已关闭),则添加一个 null 到队列中
addWorker(null, false);
}
// 如果添加队列失败,则创建一个任务线程,如果失败,则拒绝
else if (!addWorker(command, false))//3
reject(command);//4
}从上面可以看出最重要的方法。addWorker()和 workQueue.offer().
//firstTask表示某个线程的第一个任务,core=true 表示创建core线程 false表示创建maximumPoolSize线程
private boolean addWorker(Runnable firstTask, boolean core) {
w = new Worker(firstTask);final Thread t = w.thread;
if (workerAdded) { t.start();// 线程开启
}
}
public void run() {//线程调用Worker类的run
runWorker(this);
}
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;//1 要执行的任务
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {//这个while 循环 使得当前线程 不会退出 一直取任务执行
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);//3 执行前扩展
Throwable thrown = null;
try {
task.run();//2 任务执行
} 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);//4执行后扩展
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
//看下Worker 的构造方法
Worker(Runnable firstTask) {
setState(-1); //
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);//!!此处得到新的线程,并封装了任务
}
#2 submit方式提交
ExecutorService#submit(task)
--AbstractExecutorService#submit()
--AbstractExecutorService#newTaskFor
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
看看newTaskFor
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { return new FutureTask<T>(callable);
}
看看FutureTask类
FutureTask是一个Runnable ,看它的run()
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();//1 返回结果.
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);//设置异常
}
if (ran)
set(result);//2结果设置
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}那么如何得到结果呢?FutureTask#get()
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}