创建线程池的几种方式 核心参数 以及线程池工具类

目录

Executors 4种创建方式

线程池优点

不推荐使用Executors 创建线程池原因

通过ThreadPoolExecutor创建线程池

创建线程池工具类


Executors 4种创建方式

(1)newCachedThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理需求,可灵活回收空闲线程,若无可回收,则新建线程。

(2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待

(3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行

(4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行

线程池优点

(1)重用存在的线程,减少对象创建、消亡的开销,性能佳

(2)可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

(3)提供定时执行、定期执行、单线程、并发数控制等功能。

不推荐使用Executors 创建线程池原因

(摘自阿里编码规约)

线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。说明:Executors各个方法的弊端:1)newFixedThreadPool和newSingleThreadExecutor:   主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。2)newCachedThreadPool和newScheduledThreadPool:   主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。

通过ThreadPoolExecutor创建线程池

ThreadPoolExecutor 是线程池的核心实现。线程的创建和终止需要很大的开销,线程池中预先提供了指定数量的可重用线程,所以使用线程池会节省系统资源,并且每个线程池都维护了一些基础的数据统计,方便线程的管理和监控。

7个核心参数

1. corePoolSize:线程池中的核心线程数,核心线程会一直存在,即使没有任务执行。
2. maximumPoolSize:线程池最大线程数 字面意思
3. keepAliveTime:当线程数大于核心数时,这是多余空闲线程在终止前等待新任务的最长时间。
4. unit:keepAliveTime的时间单位。
5. workQueue:任务队列,被提交但尚未被执行的任务(阻塞队列)

        SynchronousQueue 直接提交队列 没有容量,每执行一个插入操作就会阻塞。一般不用

        ArrayBlockingQueue  先进先出 基于数组的队列 读写锁不分离 

        LinkedBlockingQueue 先进先出 基于链表默认无界队列,使用必须给定大小 读写分离 效率高 

        PriorityBlockingQueue 可以设置优先级的队列


6. threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般用默认的即可。
7. handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数。

        AbortPolicy:默认策略,在需要拒绝任务时抛出RejectedExecutionException;

        CallerRunsPolicy:直接在 execute 方法的调用线程中运行被拒绝的任务,如果线程池已经关闭,任务将被丢弃;

        DiscardPolicy:直接丢弃任务;

        DiscardOldestPolicy:丢弃队列中等待时间最长的任务,并执行当前提交的任务,如果线程池已经关闭,任务将被丢弃。

创建线程池工具类


import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * @author t
 */
public class ThreadUtils {
    private static final Logger logger = LoggerFactory.getLogger(ThreadUtils.class);

    public volatile static ThreadPoolExecutor threadPoolExecutor;

    private final static String THREAD_NAME = "thread-t";

    private final static String SINGLE_THREAD_NAME = "single-thread-t";

    /**
     * 获取线程工厂
     *
     * @return ThreadFactory
     */
    public static ThreadFactory getThreadFactory(String threadName) {
        return new ThreadFactoryBuilder()
                .setNameFormat(threadName + "-%d")
                .setUncaughtExceptionHandler((t, e) -> {
                    logger.error("线程报错", e);
                })
                // 守护线程
                .setDaemon(true).build();
    }

    /**
     * 获取线程池对象
     *
     * @return ExecutorService
     */
    public static ThreadPoolExecutor getThreadPoolExecutor() {
        try {
            return new ThreadPoolExecutor(
                    4,
                    16,
                    10,
                    TimeUnit.SECONDS,
                    new LinkedBlockingDeque<>(100),
                    getThreadFactory(THREAD_NAME),
                    new ThreadPoolExecutor.AbortPolicy());
        } catch (Exception e) {
            logger.error("创建线程池发生异常", e);
        }
        return threadPoolExecutor;
    }

    /**
     * 获取单利线程池对象
     *
     * @return ExecutorService
     */
    public static ExecutorService getSingleThreadPoolExecutor() {
        try {
            if (threadPoolExecutor == null) {
                synchronized (ThreadUtils.class) {
                    if (threadPoolExecutor == null) {
                        threadPoolExecutor = new ThreadPoolExecutor(
                                10,
                                20,
                                10,
                                TimeUnit.SECONDS,
                                new LinkedBlockingDeque<>(100),
                                getThreadFactory(SINGLE_THREAD_NAME),
                                new ThreadPoolExecutor.AbortPolicy());
                    }
                }
            }
        } catch (Exception e) {
            logger.error("创建单例线程池发生异常", e);
        }
        return threadPoolExecutor;
    }

}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值