demo代码:

    1. public class ThreadPoolExecutorSample {
    2. public static void main(String[] args) throws IOException, InterruptedException {
    3. //阻塞队列,大小设置为2,方便查看运行过程
    4. int blockQueueSize = 2;
    5. BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(blockQueueSize);
    6. //线程工厂,可以为线程池启动的线程做一些自定义的处理,比如做标识方便区分查看结果
    7. ThreadFactory threadFactory = new MyTreadFactory();
    8. //拒绝策略,比如拒绝执行了可以在里面自定义一些返回内容
    9. RejectedExecutionHandler handler = new MyIgnoreHandle();
    10. //核心线程数为2,最大线程数为3,空闲时间为10,设置小点是为了方便打印查看执行过程
    11. int corePoolSize = 2;
    12. int maximumPoolSize = 3;
    13. ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 2000, TimeUnit.SECONDS, workQueue, threadFactory, handler);
    14. //这里是预启动所有的核心线程,不加这句话如果没有任务的情况下线程池里是没有线程的
    15. //executor.prestartAllCoreThreads();
    16. for (int i = 1; i <= 10; i++) {
    17. MyTask task = new MyTask(String.valueOf(i));
    18. executor.execute(task);
    19. Thread.sleep(10);
    20. }
    21. }
    22. static class MyTreadFactory implements ThreadFactory {
    23. private final AtomicInteger mThreadNum = new AtomicInteger(1);
    24. @Override
    25. public Thread newThread(Runnable r) {
    26. String name = "";
    27. if(mThreadNum.get()<=2){
    28. name = "my-thread-" + mThreadNum.get() + "-核心线程";
    29. }
    30. else{
    31. name = "my-thread-" + mThreadNum.get() + "-非核心线程";
    32. }
    33. Thread t = new Thread(r, name);
    34. System.out.println(t.getName() + " has been created");
    35. mThreadNum.getAndIncrement();
    36. return t;
    37. }
    38. }
    39. static class MyIgnoreHandle implements RejectedExecutionHandler {
    40. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    41. //这里是可以重写拒绝队列的,比如一些不允许拒绝的任务我们可以写到redis缓存里,再专门开一个线程来重新执行拒绝的任务
    42. //这里就简单做日志输出记录了
    43. doLog(r, e);
    44. }
    45. private void doLog(Runnable r, ThreadPoolExecutor e) {
    46. System.err.println( r.toString() + " rejected");
    47. }
    48. }
    49. static class MyTask implements Runnable {
    50. private String name;
    51. public MyTask(String name) {
    52. this.name = name;
    53. }
    54. @Override
    55. public void run() {
    56. try {
    57. System.out.println(this.toString() + " is running!");
    58. //让任务执行慢点
    59. Thread.sleep(6000);
    60. } catch (InterruptedException e) {
    61. e.printStackTrace();
    62. }
    63. }
    64. public String getName() {
    65. return name;
    66. }
    67. @Override
    68. public String toString() {
    69. return "MyTask [name=" + name + "]";
    70. }
    71. }
    72. }

    demo参数设置:
    阻塞队列数:2
    核心线程数为:2
    最大线程数为:3,那非核心线程数只有1个
    执行结果:
    image.png
    demo执行结果分析:
    在1-10的for循环体里:
    1.任务1进来,此时线程池还没有线程,线程池此时会创建第1个核心线程来执行任务。
    2.任务2进来,此时线程池只有1个核心线程,线程池此时会创建第2个核心线程来执行任务2。
    3.任务3进来,此时线程池已经有2个核心线程,达到预设的核心线程数,任务3只能去阻塞队列排队了。
    4.任务4进来,此时线程池已经有2个核心线程,达到预设的核心线程数,任务4只能去阻塞队列排队了。
    5.任务5进来,此时线程池已经有2个核心线程,达到预设的核心线程数,任务5只能去阻塞队列排队了,但发现此时的阻塞队列也达到预设的阻塞队列数,此时线程池会去创建非核心线程3出来执行任务5。
    6.任务6进来,此时线程池里有2个核心线程和1个非核心线程,3个线程数已经达到预设的最大线程数了,并且3个线程都已经有未执行完成的任务,分别是任务1、任务2和任务5,并且阻塞队列也已经排满了任务,分别是任务3和任务4,那么任务6就只有被拒绝了,拒绝策略里的日志打印也便执行了。
    7.后面的任务7、8、9、10都是一样的,线程池满了,阻塞队列也满了,只有被拒绝了。