ThreadPoolExecutor

1,062 阅读4分钟
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);
}