java线程池原理

目录

什么是线程池

为什么使用线程池?

阻塞队列

线程池分类

线程池的核心参数

线程池队列拒绝策略

线程池的状态

整个流程

线程池源码分析


什么是线程池

线程池和数据库连接池非常类似,可以统一管理和维护线程,减少没有必要的开销。

为什么使用线程池?

1.降低资源消耗

通过重复利用创建好的线程,来降低我们创建和销毁线程的造成资源的消耗。

2.提高响应速度

任务执行后,直接通过已经创建好的线程执行,提高我们的响应速度。

3.提高线程的可管理性

线程资源和我们服务器的cpu资源息息相关,不能任意地无限制创建,不仅消耗我们系统资源,还会降低系统的响应速度。使用线程池可以统一监控、调度和调优。

阻塞队列

1.ArrayBlockingQueue

有界队列,基于数组结构,按照队列FIFO原则对元素排序;

2.LinkedBlockingQueue

无界队列,基于链表结构,按照队列FIFO原则对元素排序,Executors.newFixedThreadPool()使用了这个队列; 无界默认是Integer.MAX_VALUE,有界则是 可以自己定义

3.SynchronousQueue:

同步队列,该队列不存储元素,每个插入操作必须等待另一个线程调用移除操作,否则插入操作会一直被阻塞,Executors.newCachedThreadPool()使用了这个队列;

4.PriorityBlockingQueue:

优先级队列,具有优先级的无限阻塞队列。

线程池分类

Executor框架的最顶层实现是ThreadPoolExecutor类,Executors工厂类中提供了以下四种:

newScheduledThreadPool:定时任务线程池

newSingleThreadScheduledExecutor:只有一个线程的定时任务线程池

newFixedThreadPool:固定线程数量的线程池

newCachedThreadPool:可缓存的线程池

在实际项目使用过程中,一般不会使用自带的这几种创建方式,下面会将解具体原因。

线程池的核心参数

corePoolSize: 核心池的大小。 当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;

maximumPoolSize: 线程池最大线程数,它表示在线程池中最多能创建多少个线程;

keepAliveTime:  表示超出corePoolSize的线程没有任务执行时最多保持多久时间会终止;

unit: 参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性;

workQueue: 阻塞队列,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中,通常初始化时需要指定队列大小;

threadFactory: 创建线程的工厂,指定线程前缀,来识别不同业务所需的线程池,方便问题的排查;

handler:拒绝策略,当任务达到maximumPoolSize最大线程数量时,通过指定不同的拒绝策略,来对当前任务做具体的处理。

线程池队列拒绝策略

ThreadPoolExecutor类有几个内部实现类来处理拒绝任务:
1.AbortPolicy 丢弃任务,抛运行时异常
2.CallerRunsPolicy 执行任务
3.DiscardPolicy 忽视,什么都不会发生
4.DiscardOldestPolicy 从队列中踢出最先进入队列(最后一个执行)的任务
5.实现RejectedExecutionHandler接口,可自定义处理器

线程池的状态

1.RUNNING:线程池能够接受新任务,以及对新添加的任务进行处理。

2.SHUTDOWN:线程池不可以接受新任务,但是可以对已添加的任务进行处理。

3.STOP:线程池不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。

4.TIDYING:当所有的任务已终止,ctl记录的"任务数量"为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行构造函数5.terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。

6.TERMINATED:线程池彻底终止的状态。

整个流程

下图是线程池主要的4个流程,结合了线程池的具体源码。

线程池源码分析

new线程池时,初始化线程池参数:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
 

调用线程池的execute():

    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
 
        int c = ctl.get();
        //1.小于核心线程池时,创建新的线程
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        //2.任务大于核心线程时,将任务放到阻塞队列中
        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);
        }
        //3.大于最大线程时
        else if (!addWorker(command, false))
        //4.执行拒绝策略
            reject(command);
    }

Worker分析

将每个任务封住为Worker:

    private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable

然后通过while循环获取阻塞队列中的任务, 调用task.run()就会执行我们具体的任务。

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知始行末

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值