深入理解线程池ThreadPoolExecutor

本文详细介绍了线程池的工作原理和技术细节,包括线程池的状态转换、关键参数配置及拒绝策略等。同时,还提供了如何自定义线程名称的方法。

概述

  • 使用线程池技术可以降低资源的消耗,提高响应速度和线程的可重复利用性
  • 当提交一个新任务到线程池后,线程池首先会判断核心线程池(corePoolSize)里的线程是否都在执行任务,如果不是则创建一个新的工作线程来执行任务。如果核心线程池corePoolSize的线程都被占用在执行任务,线程判断工作队列是否已满,如果工作队列没有满:则将新提交的任务存储到工作队列中,如果工作队列已满:判断线程池(maximumPoolSize)的线程是否处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果线程池已满,则交给饱和策略处理这个任务。

 

线程池的五种状态

  • RUNNING(运行中):线程池的初始化状态。线程池处在RUNNING状态时,能够接受新任务,以及对已添加的任务进行处理。
  • SHUTDOWN(关掉):调用线程池的shutdown()接口时,线程池由RUNNING>>SHUTDOWN。处在SHUTDOWN状态时,不接搜新任务,但是能处理已添加的任务。
  • STOP(停止):调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN)>> STOP。处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
  • TIDYING(整理):当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由SHUTDOWN >> TIDYING。当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP >> TIDYING。
  • TERMINATED(终止):线程池彻底终止,就变成TERMINATED状态。线程池处在TIDYING状态时,执行完terminated()之后,就会由TIDYING >> TERMINATED。

 

线程池的参数

  • corePoolSize: 初始化指定的核心线程数量
  • maximumPoolSize:允许的最大线程数。当前的线程数小于maximumPoolSize,则会新建线程来执行任务
  • keepAliveTime:线程空闲的时间
  • unit:keepAliveTime的单位
  • workQueue:保存等待执行的任务的阻塞队列。初始化核心线程池已满时,队列未满会吧任务存储到队列中。

可供选择的几种阻塞队列

  1. ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。
  2. LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
  3. SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。
  4. PriorityBlockingQueue:一个具有优先级得无限阻塞队列

 

  • PriorityBlockingQueue:一个具有优先级得无限阻塞队列
  • threadFactory:用于设置创建线程的工厂。不指定 则是默认
  • handler:线程池的拒绝策略。线程池中的线程已经饱和了,而且阻塞队列也已经满了,则线程池会选择一种拒绝策略来处理该任务

线程池提供的四种拒绝策略,也可以实现自己的拒绝策略:

  • AbortPolicy:默认策略 抛出异常
  • CallerRunsPolicy:由当前调用者所在的线程来执行任务
  • DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务
  • DiscardPolicy:直接丢弃多余的任务
 ThreadPoolExecutor executor=new
                ThreadPoolExecutor(1,1,
                10,TimeUnit.SECONDS,new ArrayBlockingQueue<>(1),new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i <5 ; i++) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                }
            });
        }
        executor.shutdown();
    }

常用方法

  • getCorePoolSize() 返回核心线程数。
  • getMaximumPoolSize() 返回允许的最大线程数。
  • getPoolSize() 返回池中的当前线程数。
  • getQueue() 返回此执行程序使用的任务队列。
  • isShutdown() 如果此执行程序已关闭,则返回 true。
  • isTerminated() 如果关闭后所有任务都已完成,则返回 true。
  • execute(Runnable command) 在将来某个时间执行给定任务
  • shutdown() 按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。
  • shutdownNow() 尝试停止所有的活动执行任务、暂停等待任务的处理,并返回等待执行的任务列表。

自定义线程名称 

public class ThreadPoolExecutorTest {

    // 命名线程工厂
    static class NamedThreadFactory 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;

        NamedThreadFactory(String name) {

            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            if (null == name || name.isEmpty()) {
                name = "pool";
            }

            namePrefix = name + "-" + 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;
        }
    }

    public static void main(String[] args) {
        ThreadPoolExecutor executor=new
                ThreadPoolExecutor(1,1,
                10,TimeUnit.SECONDS,new ArrayBlockingQueue<>(1),new NamedThreadFactory("test-poll"),new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i <5 ; i++) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                }
            });
        }


        executor.shutdown();
    }
}

 

原文:https://blog.youkuaiyun.com/u010391342/article/details/88927281 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值