线程池(Thread Pool)

一、什么是线程?为什么需要线程池?

什么是线程?

线程是程序中执行的线程。 Java虚拟机允许应用程序具有多个并发运行的执行线程。

每个线程都有一个优先级。 优先级高的线程优先于优先级低的线程执行。 每个线程可能被标记为守护进程,也可能不被标记为守护进程。 当在某个线程中运行的代码创建一个新的thread对象时,新线程的优先级最初被设置为与创建线程的优先级相等,并且当且仅当创建线程是守护线程时,它(新线程)才是守护线程。

当Java虚拟机启动时,通常有一个非守护线程(它通常调用某个指定类的名为main的方法)。 Java虚拟机继续执行线程,直到发生以下任何一种情况:

  1. 类Runtime的退出方法已被调用,安全管理器已允许执行退出操作。
  2. 所有不是守护线程的线程都已经死亡,要么从对run方法的调用返回,要么抛出一个传播到run方法之外的异常。

以上摘自jdk1.8 Thread类官方注释:
在这里插入图片描述

为什么需要线程池?
概念

线程池(Thread Pool)是一种线程使用模式,线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。java.util.concurrent.Executors提供了一个java.util.concurrent.Executor接口的实现用于创建线程池。

优点
  • 降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗;
  • 提高系统响应速度,当有任务到达时,通过复用已存在的线程,无需等待新线程的创建便能立即执行;
  • 方便线程并发数的管控。因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成cpu过度切换。
    ps:cpu切换线程是有时间成本的(需要保持当前执行线程的现场,并恢复要执行线程的现场)。

二、当新任务进来时,线程池如何工作?

在这里插入图片描述

三、如何创建一个线程池?

创建线程池的构造函数

通过java.util.concurrent.ThreadPoolExecutor来进行自定义线程池,这里不建议用模板线程池,建议通过自定义的方式(具体场景具体分析)来创建线程池。
在这里插入图片描述

参数设置
  • corePoolSize

当线程池被创建后,线程池中就会有指定数量的线程被创建用来等待任务的执行,这些线程被称为核心线程。即使它们是空闲的,它们也不会被销毁。除非设置了allowCoreThreadTimeOut参数。

  • maximumPoolSize

线程池所能容纳的最大线程数量。

  • keepAliveTime

用来指定非核心线程被创建后最多可以存活的时间。

  • unit

用来设置上述时间的单位。

  • workQueue

用来保存等待执行的任务。

  • threadFactory(非必填参数,若不填写则使用默认值)

执行程序创建新线程时使用的工厂

  • handler(非必填参数,若不填写则使用默认值)

拒绝策略

四、线程池的workQueue有哪些?

1. SynchronousQueue

SynchronousQueue没有容量,是无缓冲等待队列,是一个不存储元素的阻塞队列,会直接将任务交给消费者,必须等队列中的添加元素被消费后才能继续添加新的元素。

2. LinkedBlockingQueue

LinkedBlockingQueue是一个无界缓存等待队列。当前执行的线程数量达到corePoolSize的数量时,剩余的元素会在阻塞队列里等待。

3. ArrayBlockingQueue

ArrayBlockingQueue是一个有界缓存等待队列,可以指定缓存队列的大小,当正在执行的线程数等于corePoolSize时,多余的元素缓存在ArrayBlockingQueue队列中等待有空闲的线程时继续执行,当ArrayBlockingQueue已满时,加入ArrayBlockingQueue失败,会开启新的线程去执行,当线程数已经达到最大的maximumPoolSizes时,再有新的元素尝试加入ArrayBlockingQueue时会执行拒绝策略。

五、线程池的拒绝策略有哪些?

1. AbortPolicy

丢弃任务并抛出RejectedExecutionException异常。

/**
     * A handler for rejected tasks that throws a
     * {@code RejectedExecutionException}.
     */
    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }
2. DiscardPolicy

丢弃任务,但是不抛出异常。

/**
     * A handler for rejected tasks that silently discards the
     * rejected task.
     */
    public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
3. DiscardOldestPolicy

丢弃队列最前面的任务,然后重新提交被拒绝的任务

/**
     * A handler for rejected tasks that discards the oldest unhandled
     * request and then retries {@code execute}, unless the executor
     * is shut down, in which case the task is discarded.
     */
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
4. CallerRunsPolicy

由调用线程(提交任务的线程)处理该任务

/**
     * A handler for rejected tasks that runs the rejected task
     * directly in the calling thread of the {@code execute} method,
     * unless the executor has been shut down, in which case the task
     * is discarded.
     */
    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值