Java中ThreadPoolExecutor的参数理解

简介:

一、使用Executors创建线程池

之前创建线程的时候都是用的Executors的newFixedThreadPool(),newSingleThreadExecutor(),newCachedThreadPool()这三个方法。当然Executors也是用不同的参数去new ThreadPoolExecutor

1. newFixedThreadPool()

创建线程数固定大小的线程池。 由于使用了LinkedBlockingQueue所以maximumPoolSize 没用,当corePoolSize满了之后就加入到LinkedBlockingQueue队列中。每当某个线程执行完成之后就从LinkedBlockingQueue队列中取一个。所以这个是创建固定大小的线程池。

 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
      this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

2.newSingleThreadPool()

创建线程数为1的线程池,由于使用了LinkedBlockingQueue所以maximumPoolSize 没用,corePoolSize为1表示线程数大小为1,满了就放入队列中,执行完了就从队列取一个。

  public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

3.newCachedThreadPool()

创建可缓冲的线程池。没有大小限制。由于corePoolSize为0所以任务会放入SynchronousQueue队列中,SynchronousQueue只能存放大小为1,所以会立刻新起线程,由于maxumumPoolSize为Integer.MAX_VALUE所以可以认为大小为2147483647。受内存大小限制。

 public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

二、使用ThreadPoolExecutor创建线程池

ThreadPoolExecutor的构造函数

  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

参数:

    1、corePoolSize核心线程数大小,当线程数<corePoolSize ,会创建线程执行runnable

    2、maximumPoolSize 最大线程数, 当线程数 >= corePoolSize的时候,会把runnable放入workQueue中

    3、keepAliveTime  保持存活时间,当线程数大于corePoolSize的空闲线程能保持的最大时间。

    4、unit 时间单位

    5、workQueue 保存任务的阻塞队列

    6、threadFactory 创建线程的工厂

    7、handler 拒绝策略

任务执行顺序:

    1、当线程数小于corePoolSize时,创建线程执行任务。

    2、当线程数大于等于corePoolSize并且workQueue没有满时,放入workQueue中

    3、线程数大于等于corePoolSize并且当workQueue满时,新任务新建线程运行,线程总数要小于maximumPoolSize

    4、当线程总数等于maximumPoolSize并且workQueue满了的时候执行handler的rejectedExecution。也就是拒绝策略。

ThreadPoolExecutor默认有四个拒绝策略:

    1、ThreadPoolExecutor.AbortPolicy()   直接抛出异常RejectedExecutionException

    2、ThreadPoolExecutor.CallerRunsPolicy()    直接调用run方法并且阻塞执行

    3、ThreadPoolExecutor.DiscardPolicy()   直接丢弃后来的任务

    4、ThreadPoolExecutor.DiscardOldestPolicy()  丢弃在队列中队首的任务

当然可以自己继承RejectedExecutionHandler来写拒绝策略.

int corePoolSize = 1;
        int maximumPoolSize = 2;
        int keepAliveTime = 10;
//        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>();
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(5);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        //线程池和队列满了之后的处理方式
        //1.跑出异常
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); 
        RejectedExecutionHandler handler2 = new ThreadPoolExecutor.CallerRunsPolicy();
        RejectedExecutionHandler handler3 = new ThreadPoolExecutor.DiscardPolicy();
        RejectedExecutionHandler handler4 = new ThreadPoolExecutor.DiscardOldestPolicy();

        
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, threadFactory, handler2);
        
        
        for (int j = 1; j < 15; j++) {
            threadPoolExecutor.execute(new Runnable() {
                
                public void run() {
                    
                    try {
                        System.out.println(Thread.currentThread().getName());
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    
                    
                }
            });
        }
        
        System.out.println(threadPoolExecutor);
        
    }

文章转载自 开源中国社区[https://www.oschina.net]

相关文章
|
1月前
|
存储 Java
Java-参数传值
Java-参数传值
25 4
|
1月前
|
Java
【Java每日一题】— —第二十二题:类名作参数进行方法调用的传递问题。
【Java每日一题】— —第二十二题:类名作参数进行方法调用的传递问题。
23 1
|
4月前
|
前端开发 Java 数据库连接
9:参数校验-Java Spring
9:参数校验-Java Spring
30 0
|
1月前
|
存储 Java fastjson
Java泛型-4(类型擦除后如何获取泛型参数)
Java泛型-4(类型擦除后如何获取泛型参数)
33 1
|
21天前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
60 0
|
4月前
|
Java
java 并发之ThreadPoolExecutor
java 并发之ThreadPoolExecutor
35 0
|
7天前
|
存储 监控 安全
泛型魔法:解码Java中的类型参数
泛型魔法:解码Java中的类型参数
29 0
泛型魔法:解码Java中的类型参数
|
1月前
|
前端开发 Java Spring
Java 新手如何使用Spring MVC 中的查询字符串和查询参数
Java 新手如何使用Spring MVC 中的查询字符串和查询参数
|
2月前
|
NoSQL Java Redis
【Java专题_09】生产环境Jvm参数设置
【Java专题_09】生产环境Jvm参数设置
|
2月前
|
Java
深入了解 Java 方法和参数的使用方法
方法是一块仅在调用时运行的代码。您可以将数据(称为参数)传递到方法中。方法用于执行特定的操作,它们也被称为函数。
104 4