java ThreadPoolExecutor 学习笔记
/** * @param corePoolSize * 线程池中保持的线程数量 * @param maximumPoolSize * 线程池最大可开启线程数 * @param keepAliveTime * 当线程池中的线程总量大于保持的线程数量时, * 此参数设置其中空闲的线程将保持的时间数量 * @param unit * 保持的时间单位 * 当其中的线程有空闲超过这个时间的,就将此线程杀死, * 一直到线程池的保持线程量,此时间设置将不再起作用 * @param workQueue * 线程池的等待队列 * 当需要执行的线程大于保持的线程数量时,会将此线程加入到这里设置的等待队列中 * @param threadFactory * 线程工厂类 制定了此参数后可将Runnable实现类添加到execute方法中 * 缺省使用静态内部类DefaultThreadFactory * @param handler * 当线程的等待队列超出容量时 执行的处理程序 * 缺省使用静态内部类AbortPolicy */ public ThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler){}
一、简单案例
1、Executors.newFixedThreadPool(int num)
特点:
固定线程池中可用线程数量,等待队列使用的是无界链表队列LinkedBlockingQueue,
源码:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
简单例子如下所示:
public static void jdkExecutor(){ ExecutorService exe = Executors.newFixedThreadPool(3); for(int i=0;i<5;i++){ exe.execute(new Thread(new Runnable() { @Override public void run() { System.err.println(Thread.currentThread().getName()); } })); } } //使用的是 线程的缺省 DefaultThreadFactory(静态内部类)线程工厂 public static void jdkExecutor2(){ ExecutorService exe = Executors.newFixedThreadPool(3); for(int i=0;i<5;i++){ exe.execute(new Runnable() { @Override public void run() { System.err.println(Thread.currentThread().getName()); } }); } } //自定义线程工厂 public static void jdkExecutor3(){ ExecutorService exe = Executors.newFixedThreadPool(3, new JdkFactory()); for(int i=0;i<5;i++){ exe.execute(new Runnable() { @Override public void run() { System.err.println(Thread.currentThread().getName()); } }); } } //自定义工厂 public static class JdkFactory implements ThreadFactory{ @Override public Thread newThread(Runnable r) { return new Thread( r); } }
运行结果如下所示(有三个线程在执行):
pool-1-thread-1 pool-1-thread-3 pool-1-thread-2 pool-1-thread-3 pool-1-thread-1
2、Executors.newSingleThreadExecutor()
特点:
每一个任务都是使用同一个线程完成,等待队列使用的是无界链表队列LinkedBlockingQueue,
源码:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
简单例子如下所示:
public static void jdkExecutor(){ ExecutorService exe = Executors.newSingleThreadExecutor(); for(int i=0;i<5;i++){ exe.execute(new Thread(new Runnable() { @Override public void run() { System.err.println(Thread.currentThread().getName()); } })); } } //线程工厂模式同上
运行结果如下所示:
pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1 pool-1-thread-1
3、ExecutorService newCachedThreadPool()
特点:
线程池中可用线程数量无限,等待队列使用的是同步队列SynchronousQueue,会有60秒时间等待是否让空闲线程关闭。
源码:
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
简单案例如下所示:
public static void jdkExecutor(){ ExecutorService exe = Executors.newCachedThreadPool(); for(int i=0;i<10;i++){ exe.execute(new Thread(new Runnable() { @Override public void run() { System.err.println(Thread.currentThread().getName()); } })); } } //线程工厂模式同上
运行结果如下所示:
pool-1-thread-1 pool-1-thread-3 pool-1-thread-2 pool-1-thread-4 pool-1-thread-6 pool-1-thread-2 pool-1-thread-4 pool-1-thread-3 pool-1-thread-6 pool-1-thread-5
4、直接使用JDK ThreadPoolExecutor
简单案例如下所示:
public static void jdkBaseExecuter(){ ThreadPoolExecutor treadepool = new ThreadPoolExecutor(2, 4,60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(200), new ErrorHandler()); for(int i=0;i<10;i++){ treadepool.execute(new Runnable() { @Override public void run() { System.err.println(Thread.currentThread().getName()); } }); } } //RejectedExecutionHandler缺省使用内部类AbortPolicy private static class ErrorHandler implements RejectedExecutionHandler{ @Override public void rejectedExecution(Runnable r,ThreadPoolExecutor executor) { System.err.println("队列越界:"+executor.getQueue().size()); } }
运行结果如下所示:
pool-1-thread-1 pool-1-thread-2 pool-1-thread-1 pool-1-thread-2 pool-1-thread-1 pool-1-thread-2 pool-1-thread-2 pool-1-thread-2 pool-1-thread-1 pool-1-thread-2
发现此时程序一直使用的是2个线程再执行任务,并未对保持线程数进行扩充。原因是因为此时有界缓存队列大小为200,未达到队列最大值,并不会重新开启新线程。将代码做如下改动:
ThreadPoolExecutor treadepool = new ThreadPoolExecutor(2, 4,60, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(6),new ErrorHandler());
运行结果将如下所示:
pool-1-thread-1 pool-1-thread-3 pool-1-thread-3 pool-1-thread-3 pool-1-thread-2 pool-1-thread-2 pool-1-thread-2 pool-1-thread-3 pool-1-thread-4 pool-1-thread-1
如果将有界队列值再缩小如下所示:
ThreadPoolExecutor treadepool = new ThreadPoolExecutor(2, 4,60, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(4),new ErrorHandler());
运行结果如下所示:
pool-1-thread-1 pool-1-thread-3 pool-1-thread-4 队列越界:4 pool-1-thread-2 pool-1-thread-4 pool-1-thread-4 pool-1-thread-3 pool-1-thread-1 pool-1-thread-2
就会出现队列越界错误,如果使用的是缺省ExecutionHandler将会初夏如下错误:
java.util.concurrent.RejectedExecutionException: Task xxxxxxx rejected from java.util.concurrent.ThreadPoolExecutor@56833a2e [Running, pool size = 4, active threads = 0, queued tasks = 0, completed tasks = 8] at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
所以对线程池的配置要慎重。
5、ThreadPoolTaskExecutor spring线程池
简单案例如下所示:
public static void springExecutor(){ ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); //手动创建时需要进行初始化ThreadFactory 和RejectedExecutionHandler taskExecutor.initialize(); taskExecutor.setCorePoolSize(2); taskExecutor.setMaxPoolSize(4); taskExecutor.setQueueCapacity(200); for(int i=0;i<10;i++){ taskExecutor.execute(new Thread(new Runnable() { @Override public void run() { System.err.println(Thread.currentThread().getName()); } })); } }
当然ThreadPoolTaskExecutor 也可以在Spring的XML中进行定义,然后依赖注入进来,代码如下所示:
@Autowired private TaskExecutor taskExecutor; <bean id="taskExecutor" class= "org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="2" /> <property name="maxPoolSize" value="4" /> <property name="queueCapacity" value="200" /> </bean> 注:在基于Spring容器时不需要手工进行initialize初始化,交由Spring容器初始化
运行结果如下所示:
ThreadPoolTaskExecutor-1 ThreadPoolTaskExecutor-1 ThreadPoolTaskExecutor-1 ThreadPoolTaskExecutor-1 ThreadPoolTaskExecutor-2 ThreadPoolTaskExecutor-1 ThreadPoolTaskExecutor-2 ThreadPoolTaskExecutor-1 ThreadPoolTaskExecutor-2 ThreadPoolTaskExecutor-1
具体的参数配置同上
注:以上的各种队列的不同点将于下篇进行说明
相关推荐
主要介绍了java ThreadPoolExecutor使用方法简单介绍的相关资料,需要的朋友可以参考下
主要介绍了java ThreadPoolExecutor 并发调用实例详解的相关资料,需要的朋友可以参考下
提供工厂方法来创建不同类型的线程池,这篇文章主要介绍了Java ThreadPoolExecutor 线程池的使用介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来...
主要介绍了Java ThreadPoolExecutor的参数深入理解的相关资料,需要的朋友可以参考下
ThreadPoolExecutor使用和思考
在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了...
(转)线程池:java_util_ThreadPoolExecutor 比较详细的介绍了ThreadPoolExecutor用法与属性
Java多线程实现数据切割批量执行,实现限流操作。 java线程池Executors实现数据批量操作。 批量异步Executors处理数据,实现限流操作,QPS限流。 线程池调用第三方接口限流实现逻辑。 案例适合: 1.批量处理大数据。...
主要给大家介绍了关于java线程池使用后到底要不要关闭的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
一个关于java 线程池的例子,也适合android
主要介绍了java中Executor,ExecutorService,ThreadPoolExecutor详解的相关资料,需要的朋友可以参考下
JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用
主要介绍了java 中ThreadPoolExecutor原理分析的相关资料,需要的朋友可以参考下
主要介绍了java中ThreadPoolExecutor常识汇总,线程池技术在并发时经常会使用到,java中的线程池的使用是通过调用ThreadPoolExecutor来实现的,需要的朋友可以参考下
——学习参考资料:仅用于个人学习使用! 本代码仅作学习交流,切勿用于商业用途,否则后果自负。若涉及侵权,请联系,会尽快处理! 未进行详尽测试,请自行调试!
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long
主要介绍了Java线程池ThreadPoolExecutor原理及使用实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
JDK1[1].5中的线程池(ThreadPoolExecutor)使用简介
线程池ThreadPoolExecutor实战及其原理分析(下)线程池ThreadPoolExecutor实战及其原理分析(下)线程池ThreadPoolExecutor实战及其原理分析(下)线程池ThreadPoolExecutor实战及其原理分析(下)线程池ThreadPoolExecutor...
Java,线程池,ThreadPoolExecutor