线程池ThreadPoolExecutor使用简介
一、简介
线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> 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;
- }
- }
说明:
1、在这段程序中,一个任务就是一个Runnable类型的对象,也就是一个ThreadPoolTask类型的对象。
2、一般来说任务除了处理方式外,还需要处理的数据,处理的数据通过构造方法传给任务。
3、在这段程序中,main()方法相当于一个残忍的领导,他派发出许多任务,丢给一个叫 threadPool的任劳任怨的小组来做。
这个小组里面队员至少有两个,如果他们两个忙不过来,任务就被放到任务列表里面。
如果积压的任务过多,多到任务列表都装不下(超过3个)的时候,就雇佣新的队员来帮忙。但是基于成本的考虑,不能雇佣太多的队员,至多只能雇佣 4个。
如果四个队员都在忙时,再有新的任务,这个小组就处理不了了,任务就会被通过一种策略来处理,我们的处理方式是不停的派发,直到接受这个任务为止(更残忍!呵呵)。
因为队员工作是需要成本的,如果工作很闲,闲到 3SECONDS都没有新的任务了,那么有的队员就会被解雇了,但是,为了小组的正常运转,即使工作再闲,小组的队员也不能少于两个。
4、通过调整 produceTaskSleepTime和 consumeTaskSleepTime的大小来实现对派发任务和处理任务的速度的控制,改变这两个值就可以观察不同速率下程序的工作情况。
5、通过调整4中所指的数据,再加上调整任务丢弃策略,换上其他三种策略,就可以看出不同策略下的不同处理方式。
6、对于其他的使用方法,参看jdk的帮助,很容易理解和使用。
另一个例子:
- 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线程池ThreadPoolExecutor使用简介
一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...
- 线程池ThreadPoolExecutor使用简介(转)
一.简介 线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int ...
- [转载]线程池ThreadPoolExecutor使用简介
一.简介 线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int ...
- 关于线程池ThreadPoolExecutor使用总结
本文引用自: http://blog.chinaunix.net/uid-20577907-id-3519578.html 一.简介 线程池类为 java.util.concurrent.Thread ...
- 多线程学习笔记八之线程池ThreadPoolExecutor实现分析
目录 简介 继承结构 实现分析 ThreadPoolExecutor类属性 线程池状态 构造方法 execute(Runnable command) addWorker(Runnable firstT ...
- 线程池ThreadPoolExecutor使用
一.简介 线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int ...
- 线程池ThreadPoolExecutor
线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int maxi ...
- [转] 引用 Java自带的线程池ThreadPoolExecutor详细介绍说明和实例应用
PS: Spring ThreadPoolTaskExecutor vs Java Executorservice cachedthreadpool 引用 [轰隆隆] 的 Java自带的线程池Thre ...
- android线程池ThreadPoolExecutor的理解
android线程池ThreadPoolExecutor的理解 线程池 我自己理解看来.线程池顾名思义就是一个容器的意思,容纳的就是ThreadorRunable, 注意:每一个线程都是需要CPU分配 ...
随机推荐
- 【转】QTP书写程序技巧
一.添加固定注释 新建一TXT文档,将要添加的注释写在文档中 将文档名改为:ActionTemplate.mst 将文件放到QTP安装目录的dat文件夹中 设置好后,在QTP中每次新建一个测试就会自动 ...
- 转载: pyExcelerator(Python操作Excel内库)API 文档
1.pyExcelerator 主要通过俩个Object操作Excel: Workbook 和Worksheet2.pyExcelerator 读取Excel文件 parase_xls(filenam ...
- c语言结构体中的冒号的用法
结构体中常见的冒号的用法是表示位域. 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省 ...
- hdoj 2502 月之数
月之数 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- 关于PHP程序员解决问题的能力
这个话题老生长谈了,在面试中必然考核的能力中,我个人认为解决问题能力是排第一位的,比学习能力优先级更高.解决问题的能力既能看出程序员的思维能力,应变能力,探索能力等,又可以看出他的经验.如果解决问题能 ...
- word模版另存为网页(*.htm,*.html),转为jsp页面并加入数据后导出成word
word模版另存为网页之后,将html格式的文件转为jsp页面,在页面上加入相应的动态值,加入的值中包含图片,这个该怎么处理??另外导出的文件需要拷贝到不同的地方(无法联网)使用. <%@ pa ...
- Introspector(内省)简单演示样例 与 简单应用
简单演示样例: package com.asdfLeftHand.test; import java.beans.BeanDescriptor; import java.beans.BeanInfo; ...
- json xmpp
https://github.com/lamfire/jspp http://blog.csdn.net/nomousewch/article/category/823687 http://my.os ...
- JQuery Kendo UI使用技巧总结
Kendo UI开发总结 By Gloomyfish on 2013-04-25 在Grid中支持分页刷新: scrollable: {virtual : true }, 在Gr ...
- [Node.js] Web Scraping with Pagination and Advanced Selectors
When web scraping, you'll often want to get more than just one page of data. Xray supports paginatio ...