先看JUC包自带的一个资源 线程池执行器:
初始化参数如下
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( corePoolSize, // 核心线程数量 maximumPoolSize, // 峰值线程数量 keepAliveTime, // 保留时限,当线程数量超出峰值数量时,保留多久后释放多余的线程资源 timeUnit, // 时限单位 synchronousQueue, // 工作队列,存放需要提交给执行器执行的任务 threadFactory, // 线程工厂 callerRunsPolicy // 任务拒绝执行处理器(拒绝策略) );
基础参数配置:
峰值上限,保留时限,根据实际业务情况来设置
/** * 线程数量参数 计算公式参考 * https://www.cnblogs.com/warehouse/p/10810338.html */ int cpuCount = Runtime.getRuntime().availableProcessors(); int corePoolSize = 2 * cpuCount; // 核心线程数量(初始化和空闲存留时的线程数量) int maximumPoolSize = 100; // 最大线程数量 线程占用峰值上限数量 long keepAliveTime = 100; // 保留时长(当前线程数量大于核心数量时保留多久后释放多余线程) TimeUnit timeUnit = TimeUnit.SECONDS; // 保留时长单位
几种工作队列:
/** * SynchronousQueue队列 * SynchronousQueue是一个特殊的BlockingQueue * 它没有容量,每执行一个插入操作就会阻塞,需要再执行一个删除操作才会被唤醒 * 反之每一个删除操作也都要等待对应的插入操作。 */ SynchronousQueue<Runnable> synchronousQueue = new SynchronousQueue<>(); /** * ArrayBlockingQueue有界任务队列,若有新的任务需要执行时,线程池会创建新的线程, * 直到创建的线程数量达到corePoolSize时,则会将新的任务加入到等待队列中。 * 若等待队列已满,即超过ArrayBlockingQueue初始化的容量,则继续创建线程,直到线程数量达到maximumPoolSize设置的最大线程数量, * 若大于maximumPoolSize,则执行拒绝策略。在这种情况下,线程数量的上限与有界任务队列的状态有直接关系, * 如果有界队列初始容量较大或者没有达到超负荷的状态,线程数将一直维持在corePoolSize以下, * 反之当任务队列已满时,则会以maximumPoolSize为最大线程数上限。 */ ArrayBlockingQueue<Runnable> arrayBlockingQueue = new ArrayBlockingQueue<>(10); /** * 无界任务队列,线程池的任务队列可以无限制的添加新的任务, * 而线程池创建的最大线程数量就是你corePoolSize设置的数量, * 也就是说在这种情况下maximumPoolSize这个参数是无效的, * 哪怕你的任务队列中缓存了很多未执行的任务,当线程池的线程数达到corePoolSize后,就不会再增加了;\ * 若后续有新的任务加入,则直接进入队列等待, * 当使用这种任务队列模式时,一定要注意你任务提交与处理之间的协调与控制, * 不然会出现队列中的任务由于无法及时处理导致一直增长,直到最后资源耗尽的问题。 */ LinkedBlockingQueue<Runnable> linkedBlockingQueue = new LinkedBlockingQueue<>(); /** * PriorityBlockingQueue它其实是一个特殊的无界队列,它其中无论添加了多少个任务,线程池创建的线程数也不会超过corePoolSize的数量 * ,只不过其他队列一般是按照先进先出的规则处理任务,而PriorityBlockingQueue队列可以自定义规则根据任务的优先级顺序先后执行。 */ PriorityBlockingQueue<Runnable> priorityBlockingQueue = new PriorityBlockingQueue<>();
线程工厂使用默认工厂提供:
/** * ThreadFactory */ ThreadFactory threadFactory = Executors.defaultThreadFactory();
拒绝策略一般使用第4个,谁提交谁执行:
/** * 当线程需求数量超出预设峰值上限,如何拒绝线程资源获取 * 1、直接丢弃 * 2、替换工作队列的最后一个 * 3、抛异常中断 * 4、哪个线程提交的任务就让那个线程执行 * 5、自定义 */ ThreadPoolExecutor.DiscardPolicy discardPolicy = new ThreadPoolExecutor.DiscardPolicy(); ThreadPoolExecutor.DiscardOldestPolicy discardOldestPolicy = new ThreadPoolExecutor.DiscardOldestPolicy(); ThreadPoolExecutor.AbortPolicy abortPolicy = new ThreadPoolExecutor.AbortPolicy(); ThreadPoolExecutor.CallerRunsPolicy callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy(); RejectedExecutionHandler handler = (r, executor) -> { // 入参一个runnable 和 executor };
Spring封装的线程池:
任务执行器
1、不需要设置队列类型,但是要提供队列长度
2、可以设置线程名称前缀
3、当所有任务执行完毕时,释放线程池资源
4、需要调用初始化方法
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maximumPoolSize); executor.setQueueCapacity((int)(maximumPoolSize * 1.5D)); executor.setKeepAliveSeconds(60); executor.setThreadNamePrefix("线程名称前缀"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.setWaitForTasksToCompleteOnShutdown(true); /* 等待所有任务结束后再关闭线程池 */ executor.initialize();
要设置手动释放资源,就不要使用Spring注册成Bean配置了,那这个线程池就是临时在业务方法需要调用一下
标签:Java,队列,配置,任务,线程,executor,new,ThreadPoolExecutor From: https://www.cnblogs.com/mindzone/p/17447474.html