Java线程池,看这一篇足够

Java线程池

上一篇《@Async注解的注意事项》说到@Async注解要配合自定义线程池一起使用,这一节说下Java的线程池。

1. Executors提供6个线程池快捷创建方式

    public static void main(String[] args) {
        // 定长线程池,核心线程数和最大线程数一致
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        // 缓存线程池,核心线程数为0,最大线程数Integer最大值,线程存活时间超长
        ExecutorService executorService1 = Executors.newCachedThreadPool();
        // 定时线程池,可以设置执行时间
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        // 单线程线程池,核心线程和最大线程数都为1
        ExecutorService executorService2 = Executors.newSingleThreadExecutor();
        // 核心线程数为1的定时线程池,可以执行定时任务
        ScheduledExecutorService scheduledExecutorService1 = Executors.newSingleThreadScheduledExecutor();
        // 窃取线程池,并行执行线程,依赖cpu个数
        ExecutorService executorService3 = Executors.newWorkStealingPool(3);
    }

通过调试依次看下各个线程池的实际参数

newFixedThreadPool,定长线程池

在这里插入图片描述

可见,corePoolSize和maxinumPoolSize数是一样的,说明线程不会销毁,且不会动态扩容。灵活性较差

newCachedThreadPool,缓存线程池

在这里插入图片描述

corePoolSize为0,maxinumPoolSize为max integer,重点是keepAliveTime为600亿毫秒,线程一旦创建几乎不会销毁,容易造成OOM。

newScheduledThreadPool,定时线程池

在这里插入图片描述

maxinumPoolSize为max integer,可能造成OOM。主要特点是创建的ScheduledThreadPoolExecutor实现了ScheduledExecutorService接口,其中的schedule等方法可以设置定时执行任务。

在这里插入图片描述

newSingleThreadExecutor,单线程线程池

在这里插入图片描述

corePoolSize和maxinumPoolSize都为1,说明单个线程执行任务,未执行的任务只能堆叠在workQueue。

newSingleThreadScheduledExecutor,单线程定时线程池

在这里插入图片描述

事实上就是newScheduledThreadPool,只是corePoolSize设置为1

在这里插入图片描述

newWorkStealingPool,窃取线程池

在这里插入图片描述

这个线程池比较特殊,它是java8才提出来的,不是通过ThreadPoolExecutor创建,没有corePoolSize等参数。且线程是并行进行的,即依赖处理器进行。

我觉得下面这篇文章对我有帮助,可以阅读一下

WorkStealingPool的使用简析

以上就是通过Executors创建的6种线程池

2. ThreadPoolExecutor的7大参数

通过Executors创建的6种线程池,除了java8提出的newWorkStealingPool,其他都是直接或者间接(子类)创建

ThreadPoolExecutor类实现的。

在这里插入图片描述

ThreadPoolExecutor主要有7大参数

在这里插入图片描述

  • corePoolSize,核心线程数,线程池默认线程数,线程池创建完成时,会初始化的线程数量,当有任务进来时,通过调度线程执行任务。

  • maxinumPoolSize,最大线程数,最大线程数必须大于或等于核心线程数,核心线程正在执行任务,而有新任务进来,且当下线程数量未达到最大线程数时,会新建线程放进线程池,再用新线程执行任务。

  • keepAliveTime,存活时间,除开核心线程外的线程,也就是大于核心线程数的部分线程,如果没有任务调度该线程执行,当该线程的空闲时间达到keepALiveTime值时,会被销毁。

  • unit,时间单位,keepAliveTime的单位,一般为毫秒

  • workQueue,工作队列,也称为等待队列,任务调用时先进入工作队列,然后等待空闲线程调度。

  • threadFactory,线程工厂,指定创建线程的方式,通过线程工厂创建和销毁线程,一般使用 Executors.defaultThreadFactory() 足够,不用自定义创建该工厂类。

  • handler,拒绝策略,该类主要针对当工作队列满了之后,新的任务进来,拒绝存放在工作队列,执行的操作。其中rejectedExecution方法就是拒绝的处理方法。

    ThreadPoolExecutor提供了默认四种拒绝策略。(如果不理解可以看下源码,很简单的逻辑)

    • CallerRunsPolicy,从哪来,往哪走,由提交执行任务。
    • AbortPolicy,直接报异常
    • DiscardPolicy,什么都不做,rejectedExecution这个方法直接留空,哈哈
    • DiscardOldestPolicy,workQueue最后的任务直接踢掉,然后插入本任务

3. 自定义线程池

在阿里开发手册中明令禁止使用Executors创建线程池,通过以上第一点介绍的6种线程池可以看出,Executors提供的线程池中有些maxinumPoolSize设置为max integer,或者workQueue的容量设置为max integer(如newFixedThreadPool和newSingleThreadExecutor中,workQueue使用LinkedBlockingQueue,其size为Integer.MAX_VALUE),这存在内存溢出风险。

因而在实际开发中,最好自定义线程池。只需要实例化ThreadPoolExecutor类即可,所以自定义线程池实质上就是配置好上述第二点中的7大参数。

    public ThreadPoolExecutor myThreadExecutor(){
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                10,
                20,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        return threadPoolExecutor;
    }

最后,@Async配合自定义线程池使用,可以看我上篇文章《@Async注解的注意事项

至此,全篇结束

  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,Java线程池Java提供的一种线程管理机制,通过线程池可以更好地管理系统中的线程。下面我来介绍一下如何编写一个Java线程池工具类。 1. 创建一个ThreadPoolExecutor对象,用于管理线程池。 2. 定义一个任务类,该类实现Runnable接口,并重写run()方法,run()方法中实现具体的任务逻辑。 3. 在工具类中,定义一个execute()方法,用于向线程池提交任务,该方法接收一个Runnable对象作为参数,将该任务提交到线程池中。 4. 定义一个shutdown()方法,用于关闭线程池,该方法调用ThreadPoolExecutor的shutdown()方法即可。 5. 定义一个getActiveCount()方法,用于获取当前活跃的线程数,该方法调用ThreadPoolExecutor的getActiveCount()方法即可。 6. 可以根据需要定义其他方法,如getPoolSize()、getCorePoolSize()等。 下面是一个简单的Java线程池工具类示例: ``` import java.util.concurrent.*; public class ThreadPoolUtil { private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 5, // 核心线程数 10, // 最大线程数 60, // 线程空闲时间 TimeUnit.SECONDS, // 线程空闲时间单位 new LinkedBlockingQueue<>(), // 线程池任务队列 Executors.defaultThreadFactory(), // 线程工厂 new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 ); public static void execute(Runnable task) { threadPool.execute(task); } public static void shutdown() { threadPool.shutdown(); } public static int getActiveCount() { return threadPool.getActiveCount(); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值