ThreadPoolExecutor线程池进阶使用
一、简介
线程池类为
java.util.concurrent.ThreadPoolExecutor,常用构造方法为:
ThreadPoolExecutor(int
corePoolSize, int maximumPoolSize,
long
keepAliveTime, TimeUnit unit,
BlockingQueue
workQueue,
RejectedExecutionHandler
handler)
corePoolSize:
线程池维护线程的最少数量
maximumPoolSize:线程池维护线程的最大数量
keepAliveTime:
线程池维护线程所允许的空闲时间
unit:
线程池维护线程所允许的空闲时间的单位
workQueue:
线程池所使用的缓冲队列
handler:
线程池对拒绝任务的处理策略
一个任务通过
execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是
Runnable类型对象的run()方法。
当一个任务通过execute(Runnable)方法欲添加到线程池时:
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于
corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过
handler所指定的策略来处理此任务。
也就是:处理任务的优先级为:
核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于
corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
unit可选的参数为java.util.concurrent.TimeUnit中的几个静态属性:
NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。
workQueue我常用的是:java.util.concurrent.ArrayBlockingQueue
handler有四个选择:
ThreadPoolExecutor.AbortPolicy()
抛出java.util.concurrent.RejectedExecutionException异常
ThreadPoolExecutor.CallerRunsPolicy()
重试添加当前的任务,他会自动重复调用execute()方法
ThreadPoolExecutor.DiscardOldestPolicy()
抛弃旧的任务
ThreadPoolExecutor.DiscardPolicy()
抛弃当前的任务
二、一般用法举例
- package
demo; - import java.io.Serializable;
- import java.util.concurrent.ArrayBlockingQueue;
- import java.util.concurrent.ThreadPoolExecutor;
- import java.util.concurrent.TimeUnit;
- public class TestThreadPool2
- {
- private static int
produceTaskSleepTime = 2; - private static int
produceTaskMaxNumber = 10; - public static void
main(String[] args) - {
- // 构造一个线程池
- ThreadPoolExecutor threadPool
= new
ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(3), - new ThreadPoolExecutor.DiscardOldestPolicy());
- for (int i = 1; i <=
produceTaskMaxNumber; i++) - {
- try
- {
- //
产生一个任务,并将其加入到线程池 - String task = "task@ "
+ i; - System.out.println("put " +
task); - threadPool.execute(new ThreadPoolTask(task));
- // 便于观察,等待一段时间
- Thread.sleep(produceTaskSleepTime);
- }
- catch (Exception
e) - {
- e.printStackTrace();
- }
- }
- }
- }
- /**
- * 线程池执行的任务
- */
- class ThreadPoolTask implements Runnable,
Serializable - {
- private static final
long serialVersionUID = 0; - private static int
consumeTaskSleepTime = 2000; - // 保存任务所需要的数据
- private Object threadPoolTaskData;
- ThreadPoolTask(Object tasks)
- {
- this.threadPoolTaskData = tasks;
- }
- public void run()
- {
- //
处理一个任务,这里的处理方式太简单了,仅仅是一个打印语句 - System.out.println(Thread.currentThread().getName());
- System.out.println("start .." +
threadPoolTaskData); - try
- {
- // //便于观察,等待一段时间
- Thread.sleep(consumeTaskSleepTime);
- }
- catch (Exception
e) - {
- e.printStackTrace();
- }
- threadPoolTaskData = null;
- }
- public Object getTask()
- {
- return this.threadPoolTaskData;
- }
- }
另一个例子:
- package
demo; - import java.util.Queue;
- import java.util.concurrent.ArrayBlockingQueue;
- import java.util.concurrent.ThreadPoolExecutor;
- import java.util.concurrent.TimeUnit;
- public class ThreadPoolExecutorTest
- {
- private static int
queueDeep = 4; - public void createThreadPool()
- {
- /*
- * 创建线程池,最小线程数为2,最大线程数为4,线程池维护线程的空闲时间为3秒,
- * 使用队列深度为4的有界队列,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,
- * 然后重试执行程序(如果再次失败,则重复此过程),里面已经根据队列深度对任务加载进行了控制。
- */
- ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(queueDeep), - new ThreadPoolExecutor.DiscardOldestPolicy());
- // 向线程池中添加 10 个任务
- for (int i = 0; i < 10;
i++) - {
- try
- {
- Thread.sleep(1);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- while (getQueueSize(tpe.getQueue()) >=
queueDeep) - {
- System.out.println("队列已满,等3秒再添加任务");
- try
- {
- Thread.sleep(3000);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- TaskThreadPool ttp = new TaskThreadPool(i);
- System.out.println("put i:" +
i); - tpe.execute(ttp);
- }
- tpe.shutdown();
- }
- private synchronized int getQueueSize(Queue queue)
- {
- return queue.size();
- }
- public static void
main(String[] args) - {
- ThreadPoolExecutorTest test =
new ThreadPoolExecutorTest(); - test.createThreadPool();
- }
- class TaskThreadPool implements Runnable
- {
- private int index;
- public TaskThreadPool(int
index) - {
- this.index =
index; - }
- public void run()
- {
- System.out.println(Thread.currentThread() + " index:"
+ index); - try
- {
- Thread.sleep(3000);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- }
- }
ThreadPoolExecutor线程池进阶使用的更多相关文章
- Java线程池进阶
线程池是日常开发中常用的技术,使用也非常简单,不过想使用好线程池也不是件容易的事,开发者需要不断探索底层的实现原理,才能在不同的场景中选择合适的策略,最大程度发挥线程池的作用以及避免踩坑. 一.线程池 ...
- 13.ThreadPoolExecutor线程池之submit方法
jdk1.7.0_79 在上一篇<ThreadPoolExecutor线程池原理及其execute方法>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法 ...
- ThreadPoolExecutor 线程池的源码解析
1.背景介绍 上一篇从整体上介绍了Executor接口,从上一篇我们知道了Executor框架的最顶层实现是ThreadPoolExecutor类,Executors工厂类中提供的newSchedul ...
- j.u.c系列(01) ---初探ThreadPoolExecutor线程池
写在前面 之前探索tomcat7启动的过程中,使用了线程池(ThreadPoolExecutor)的技术 public void createExecutor() { internalExecutor ...
- Java并发——ThreadPoolExecutor线程池解析及Executor创建线程常见四种方式
前言: 在刚学Java并发的时候基本上第一个demo都会写new Thread来创建线程.但是随着学的深入之后发现基本上都是使用线程池来直接获取线程.那么为什么会有这样的情况发生呢? new Thre ...
- ThreadPoolExecutor 线程池
TestThreadPoolExecutorMain package core.test.threadpool; import java.util.concurrent.ArrayBlockingQu ...
- 十、自定义ThreadPoolExecutor线程池
自定义ThreadPoolExecutor线程池 自定义线程池需要遵循的规则 [1]线程池大小的设置 1.计算密集型: 顾名思义就是应用需要非常多的CPU计算资源,在多核CPU时代,我们要让每一个CP ...
- Executors、ThreadPoolExecutor线程池讲解
官方+白话讲解Executors.ThreadPoolExecutor线程池使用 Executors:JDK给提供的线程工具类,静态方法构建线程池服务ExecutorService,也就是Thread ...
- SpringBoot项目框架下ThreadPoolExecutor线程池+Queue缓冲队列实现高并发中进行下单业务
主要是自己在项目中(中小型项目) 有支付下单业务(只是办理VIP,没有涉及到商品库存),目前用户量还没有上来,目前没有出现问题,但是想到如果用户量变大,下单并发量变大,可能会出现一系列的问题,趁着空闲 ...
随机推荐
- Python 2.7 升 3.4
Ubuntu 14.04 已经安装有python3.4.0 命令行使用python3 或者创建链接即可 ln -s /usr/bin/python3 /usr/bin/python [推荐此方法,然后 ...
- java GC(Garbage Collector) | System.gc()
http://win.sy.blog.163.com/blog/static/94197186201151093543556/ Java垃圾回收调优
- ros学习网站
ROS机器人操作系统入门-中国大学MOOC https://www.bilibili.com/video/av24585414/?p=39 http://i.youku.com/i/UNDA ...
- 安装WordPress
安装php yum install php-fpm yum install php systemctl start php-fpm 启动php nginx 配置
- Centos 7 远程桌面客户端
在centos下面要远程连接windows,有人说用rdesktop,但是好像centos 7没有,对从源代码编译也不大感兴趣. 幸好还有人提醒, https://geekblood.com/2014 ...
- 【Selenium + Python】路径报错之OSError: [Errno 22] Invalid argument: './t/report/2018-03-23_11:03:12_report.html'
现象: 此问题真的是太痛苦了,查了好多资料是说路径的问题,结果还是报错,后来一点点的排查才发现原来是!!!!!! 废话不多说上原来代码: if __name__ == '__main__': star ...
- 初识vue-01
一.属性和方法 vue自定义的一些数据和方法需要绑定到实例的不同属性上面去例如数据都要绑定要data属性,方法都要绑定到methods方法实例上的data和methods里面的key值会自动挂载到vu ...
- 08 redis中hash结构及命令详解
Hash 哈希数据类型相关命令 hset key field value 作用: 把key中 filed域的值设为value 注:如果没有field域,直接添加,如果有,则覆盖原field域的值 hm ...
- ssh无密码登陆权威指南
[0]写在前面 由于ssh 实现的是免密码登陆,大致步骤是: 0.1) client通过ssh登陆到server: 0.2) server检查家目录下的.ssh文件, 并发送公钥文件 authoriz ...
- ios -- 延迟3秒触发performSelector
[self performSelector:@selector(changeText:) withObject:@"Happy aha" afterDelay:3];