ThreadPoolExecutor线程池工作原理

  • 线程池构造参数
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

corePoolSize 核心线程数
maximumPoolSize 最大工作线程数
keepAliveTime 非核心线程存活时间
unit 非核心线程存活时间keepAliveTime 的时间单位
workQueue 阻塞队列
threadFactory 线程工厂,一般用于设置线程name
handler 拒绝策略,当线程池不能处理更多的任务时会执行这个方法
CallerRunsPolicy 由当前提交任务的线程执行,即执行run方法
AbortPolicy 抛出异常RejectedExecutionHandler
DiscardPolicy 丢弃当前任务,并不会抛出异常
DiscardOldestPolicy 丢弃队列中队首的任务,放入当前任务

  • 提交任务方式
pool.submit(()->{
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

  pool.execute(()->{
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
   });

submit和execute方法的区别
1.submit 会把任务包装成FutureTask,并可以通过FutureTask.get() 获取到执行结果
2.当出现异常时,execute直接抛出异常,submit则可以通过FutureTask.get 方法捕捉到异常

  • execute执行过程
    1.首先判断当前工作线程数是否超过核心线程数corePoolSize ;

2.如果没超过,则把任务封装成Worker对象,Worker实现了Runnable接口,可以通过ThreadFactory.newThread创建一个线程,这个线程传入了Worker,并把设置到Worker的thread属性中,并添加到线程池的HashSet workers集合中;这样一来,执行创建的这个线程start方法,就是会执行Worker的run方法,而这方法又会执行他的runWorker()方法,并在这个方法中执行我们传入的任务的run方法

private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        private static final long serial
        final Thread thread;
        Runnable firstTask;
        volatile long completedTasks;

      
        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

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

3.runWorker方法是一个while循环的,当前任务执行完后,会将task置位空,再调用getTask方法从阻塞队列中获取新的任务执行

4.如果往线程池中提交任务是,当前核心线程数等于设置corePoolSize,则会将当前任务提交到工作队列中,交由第三步的核心线程通过getTask方法拿到新的任务去执行

5.如果第4步提交任务到阻塞队列中失败,则需要创建非核心工作线程去处理这些任务

6.如果第5步中发现核心线程数+非核心线程数=maximumPoolSize,则会执行拒绝策略中rejectedExecution(Runnable r, ThreadPoolExecutor executor) 方法

7.回收非核心工作线程,会判断当前的线程数是否大于核心线程数,如果大于,则调用阻塞队列的poll方法,并以创建线程池时传入的keepAliveTime设置超时时间。如果此时没有新提交的任务,则会返回null,并结束这个线程。这里并不会区分核心线程还是非核心线程,只要线程数减少到核心线程数就行了

 Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;

8.submit方法,会把任务封装成FutureTask,并调用execute方法提交任务

   public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值