一、简介
线程池类为 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()

抛弃当前的任务

二、一般用法举例

  1. package demo;
  2. import java.io.Serializable;
  3. import java.util.concurrent.ArrayBlockingQueue;
  4. import java.util.concurrent.ThreadPoolExecutor;
  5. import java.util.concurrent.TimeUnit;
  6. public class TestThreadPool2
  7. {
  8. private static int produceTaskSleepTime = 2;
  9. private static int produceTaskMaxNumber = 10;
  10. public static void main(String[] args)
  11. {
  12. // 构造一个线程池
  13. ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),
  14. new ThreadPoolExecutor.DiscardOldestPolicy());
  15. for (int i = 1; i <= produceTaskMaxNumber; i++)
  16. {
  17. try
  18. {
  19. // 产生一个任务,并将其加入到线程池
  20. String task = "task@ " + i;
  21. System.out.println("put " + task);
  22. threadPool.execute(new ThreadPoolTask(task));
  23. // 便于观察,等待一段时间
  24. Thread.sleep(produceTaskSleepTime);
  25. }
  26. catch (Exception e)
  27. {
  28. e.printStackTrace();
  29. }
  30. }
  31. }
  32. }
  33. /**
  34. * 线程池执行的任务
  35. */
  36. class ThreadPoolTask implements Runnable, Serializable
  37. {
  38. private static final long serialVersionUID = 0;
  39. private static int consumeTaskSleepTime = 2000;
  40. // 保存任务所需要的数据
  41. private Object threadPoolTaskData;
  42. ThreadPoolTask(Object tasks)
  43. {
  44. this.threadPoolTaskData = tasks;
  45. }
  46. public void run()
  47. {
  48. // 处理一个任务,这里的处理方式太简单了,仅仅是一个打印语句
  49. System.out.println(Thread.currentThread().getName());
  50. System.out.println("start .." + threadPoolTaskData);
  51. try
  52. {
  53. // //便于观察,等待一段时间
  54. Thread.sleep(consumeTaskSleepTime);
  55. }
  56. catch (Exception e)
  57. {
  58. e.printStackTrace();
  59. }
  60. threadPoolTaskData = null;
  61. }
  62. public Object getTask()
  63. {
  64. return this.threadPoolTaskData;
  65. }
  66. }

说明:

1、在这段程序中,一个任务就是一个Runnable类型的对象,也就是一个ThreadPoolTask类型的对象。

2、一般来说任务除了处理方式外,还需要处理的数据,处理的数据通过构造方法传给任务。

3、在这段程序中,main()方法相当于一个残忍的领导,他派发出许多任务,丢给一个叫 threadPool的任劳任怨的小组来做。

这个小组里面队员至少有两个,如果他们两个忙不过来,任务就被放到任务列表里面。

如果积压的任务过多,多到任务列表都装不下(超过3个)的时候,就雇佣新的队员来帮忙。但是基于成本的考虑,不能雇佣太多的队员,至多只能雇佣 4个。

如果四个队员都在忙时,再有新的任务,这个小组就处理不了了,任务就会被通过一种策略来处理,我们的处理方式是不停的派发,直到接受这个任务为止(更残忍!呵呵)。

因为队员工作是需要成本的,如果工作很闲,闲到 3SECONDS都没有新的任务了,那么有的队员就会被解雇了,但是,为了小组的正常运转,即使工作再闲,小组的队员也不能少于两个。

4、通过调整 produceTaskSleepTime和 consumeTaskSleepTime的大小来实现对派发任务和处理任务的速度的控制,改变这两个值就可以观察不同速率下程序的工作情况。

5、通过调整4中所指的数据,再加上调整任务丢弃策略,换上其他三种策略,就可以看出不同策略下的不同处理方式。

6、对于其他的使用方法,参看jdk的帮助,很容易理解和使用。

另一个例子:

    1. package demo;
    2. import java.util.Queue;
    3. import java.util.concurrent.ArrayBlockingQueue;
    4. import java.util.concurrent.ThreadPoolExecutor;
    5. import java.util.concurrent.TimeUnit;
    6. public class ThreadPoolExecutorTest
    7. {
    8. private static int queueDeep = 4;
    9. public void createThreadPool()
    10. {
    11. /*
    12. * 创建线程池,最小线程数为2,最大线程数为4,线程池维护线程的空闲时间为3秒,
    13. * 使用队列深度为4的有界队列,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,
    14. * 然后重试执行程序(如果再次失败,则重复此过程),里面已经根据队列深度对任务加载进行了控制。
    15. */
    16. ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueDeep),
    17. new ThreadPoolExecutor.DiscardOldestPolicy());
    18. // 向线程池中添加 10 个任务
    19. for (int i = 0; i < 10; i++)
    20. {
    21. try
    22. {
    23. Thread.sleep(1);
    24. }
    25. catch (InterruptedException e)
    26. {
    27. e.printStackTrace();
    28. }
    29. while (getQueueSize(tpe.getQueue()) >= queueDeep)
    30. {
    31. System.out.println("队列已满,等3秒再添加任务");
    32. try
    33. {
    34. Thread.sleep(3000);
    35. }
    36. catch (InterruptedException e)
    37. {
    38. e.printStackTrace();
    39. }
    40. }
    41. TaskThreadPool ttp = new TaskThreadPool(i);
    42. System.out.println("put i:" + i);
    43. tpe.execute(ttp);
    44. }
    45. tpe.shutdown();
    46. }
    47. private synchronized int getQueueSize(Queue queue)
    48. {
    49. return queue.size();
    50. }
    51. public static void main(String[] args)
    52. {
    53. ThreadPoolExecutorTest test = new ThreadPoolExecutorTest();
    54. test.createThreadPool();
    55. }
    56. class TaskThreadPool implements Runnable
    57. {
    58. private int index;
    59. public TaskThreadPool(int index)
    60. {
    61. this.index = index;
    62. }
    63. public void run()
    64. {
    65. System.out.println(Thread.currentThread() + " index:" + index);
    66. try
    67. {
    68. Thread.sleep(3000);
    69. }
    70. catch (InterruptedException e)
    71. {
    72. e.printStackTrace();
    73. }
    74. }
    75. }
    76. }

线程池ThreadPoolExecutor使用简介的更多相关文章

  1. java线程池ThreadPoolExecutor使用简介

    一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...

  2. 线程池ThreadPoolExecutor使用简介(转)

    一.简介 线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int ...

  3. [转载]线程池ThreadPoolExecutor使用简介

    一.简介 线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int ...

  4. 关于线程池ThreadPoolExecutor使用总结

    本文引用自: http://blog.chinaunix.net/uid-20577907-id-3519578.html 一.简介 线程池类为 java.util.concurrent.Thread ...

  5. 多线程学习笔记八之线程池ThreadPoolExecutor实现分析

    目录 简介 继承结构 实现分析 ThreadPoolExecutor类属性 线程池状态 构造方法 execute(Runnable command) addWorker(Runnable firstT ...

  6. 线程池ThreadPoolExecutor使用

    一.简介 线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int ...

  7. 线程池ThreadPoolExecutor

    线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int maxi ...

  8. [转] 引用 Java自带的线程池ThreadPoolExecutor详细介绍说明和实例应用

    PS: Spring ThreadPoolTaskExecutor vs Java Executorservice cachedthreadpool 引用 [轰隆隆] 的 Java自带的线程池Thre ...

  9. android线程池ThreadPoolExecutor的理解

    android线程池ThreadPoolExecutor的理解 线程池 我自己理解看来.线程池顾名思义就是一个容器的意思,容纳的就是ThreadorRunable, 注意:每一个线程都是需要CPU分配 ...

随机推荐

  1. ECSHOP首页调用指定分类下的商品

    转:http://bbs.ecshop.com/thread-1123207-1-1.html 调用某个分类下的商品,方法有很多种的,不过都需要先在后台设置模板那里设置显示和显示条数, 然后在需要调用 ...

  2. (转载)mysql分屏显示结果

    (转载)http://blog.csdn.net/wylkeke/article/details/7280645 linux机器: 在mysql命令行输入pager more就可以分屏显示结果了,取消 ...

  3. Java正则表达式应用总结

    http://lavasoft.blog.51cto.com/ http://lavasoft.blog.51cto.com/62575/179324      Java正则表达式应用总结   一.概 ...

  4. 打开URL操作

    /* * 打开 url 的两种方法 */ public class OpenUrl { public static void main(String[] args) { String url = &q ...

  5. 【性能测试】【Jmeter】学习(3)——查看测试结果

    监听器——聚合报告 聚合报告添加步骤:(右键点击每一个操作步骤--->“添 加”---->“监听器”---->“聚合报告”) Label:每个 JMeter 的 element(例如 ...

  6. EF多表查询方式

    5, 连接 可以的连接有Join 和 GroupJoin 方法.GroupJoin组联接等效于左外部联接,它返回第一个(左侧)数据源的每个元素(即使其他数据源中没有关联元素). using (var ...

  7. 格式化URL

    //格式化url查询参数为json function formatUrl(url){ var reg=/(?:[?&]+)([^&]+)=([^&]+)/g; var data ...

  8. HDU 1078 FatMouse and Cheese (记忆化搜索+dp)

    详见代码 #include <iostream> #include <cstdio> #include <cstdlib> #include <memory. ...

  9. jQuery技术内幕预览版.pdf2

    第二章 构造jQuery对象 jQuery对象是一个类数组对象,含有连续的整型属性.length属性和大量的jQuery方法,$()是jQuery()的缩写 构造函数jQuery() 如果调用构造函数 ...

  10. iPhone 6出现后,如何将一份设计稿支持多个尺寸?

    http://mp.weixin.qq.com/s?__biz=MzA4NTQzNTMwOA==&mid=201174413&idx=3&sn=c3fe5b3459bac288 ...