java基础回顾(六)——ThreadPoolExecutor

先来看一下构造函数

 1     public ThreadPoolExecutor(int corePoolSize,
 2                               int maximumPoolSize,
 3                               long keepAliveTime,
 4                               TimeUnit unit,
 5                               BlockingQueue<Runnable> workQueue,
 6                               ThreadFactory threadFactory,
 7                               RejectedExecutionHandler handler) {
 8         if (corePoolSize < 0 ||
 9             maximumPoolSize <= 0 ||
10             maximumPoolSize < corePoolSize ||
11             keepAliveTime < 0)
12             throw new IllegalArgumentException();
13         if (workQueue == null || threadFactory == null || handler == null)
14             throw new NullPointerException();
15         this.corePoolSize = corePoolSize;
16         this.maximumPoolSize = maximumPoolSize;
17         this.workQueue = workQueue;
18         this.keepAliveTime = unit.toNanos(keepAliveTime);
19         this.threadFactory = threadFactory;
20         this.handler = handler;
21     }

重点讲解:

1、当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。

2、当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行

3、当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务

4、当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理

5、当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程

6、当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

配置方案:

1、构造一个固定线程数目的线程池,配置的corePoolSize与maximumPoolSize大小相同,同时使用了一个无界LinkedBlockingQueue存放阻塞任务,因此多余的任务将存在再阻塞队列,不会由RejectedExecutionHandler处理 

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
} 

2、构造一个缓冲功能的线程池,配置corePoolSize=0,maximumPoolSize=Integer.MAX_VALUE,keepAliveTime=60s,以及一个无容量的阻塞队列 SynchronousQueue,因此任务提交之后,将会创建新的线程执行;线程空闲超过60s将会销毁

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
 }  

3、构造一个只支持一个线程的线程池,配置corePoolSize=maximumPoolSize=1,无界阻塞队列LinkedBlockingQueue;保证任务由一个线程串行执行

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

4、构造有定时功能的线程池,配置corePoolSize,无界延迟阻塞队列DelayedWorkQueue;有意思的是:maximumPoolSize=Integer.MAX_VALUE,由于DelayedWorkQueue是无界队列,所以这个值是没有意义的

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }  

public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }  

public ScheduledThreadPoolExecutor(int corePoolSize,
                             ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
              new DelayedWorkQueue(), threadFactory);
    } 

总结: 
1、用ThreadPoolExecutor自定义线程池,看线程是的用途,如果任务量不大,可以用无界队列,如果任务量非常大,要用有界队列,防止OOM 
2、如果任务量很大,还要求每个任务都处理成功,要对提交的任务进行阻塞提交,重写拒绝机制,改为阻塞提交。保证不抛弃一个任务 
3、最大线程数一般设为2N+1最好,N是CPU核数 
4、核心线程数,看应用,如果是任务,一天跑一次,设置为0,合适,因为跑完就停掉了,如果是常用线程池,看任务量,是保留一个核心还是几个核心线程数 
5、如果要获取任务执行结果,用CompletionService,但是注意,获取任务的结果的要重新开一个线程获取,如果在主线程获取,就要等任务都提交后才获取,就会阻塞大量任务结果,队列过大OOM,所以最好异步开个线程获取结果

时间: 2024-10-10 09:50:16

java基础回顾(六)——ThreadPoolExecutor的相关文章

java基础(六)

JAVA基础(六) 数组 数组是一组相关变量的集合. 数组是一组相关数据的集合,一组数据实际上就是一连串的的变量,数组按照使用可以分为一维数组.二维数组.多维数组. 数组能够进行一组数据的管理. 一维数组的定义:     类型 数组名[] = new 数组名[数组长度]; 一维数组的读取:    数组名[下标] = input.next(); 一个数组的最大索引号(下标)是它的元素个数(数组的长度)-1 获得数组长度:数组名.length 数组中每一个元素类型都是一样的 若要取出或写入数组中指定

四、Android学习第四天——JAVA基础回顾(转)

(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 四.Android学习第四天——JAVA基础回顾 这才学习Android的第四天,在程序中已经遇到了JAVA中以前不常用的一些知识点,赶紧回顾复习一下,打下基础 这里就做个简单的小结: 一.匿名内部类 匿名内部类说白了就是个没有被命名的JAVA类 在以下条件下使用匿名内部类比较适合: ①只用到该类的一个实例时 ②类在定义后被马上用到 ③类非常小(SUN推荐是在4行代码以下

【DAY26】JAVA 基础回顾

基础回顾 ---------------- 1.跨平台 os JVM : sandbox 1995 2.基本数据类型 byte //1 -128 ~ 127 short //2 -32768 - 32767 int //4 long //8 float //4 doule //8 char //2 boolean //1 3.引用类型 [] class interface 4.运算符 && //短路 || //短路 & // | // ^ //抑或,相同0,不同为1 >>

1、java基础回顾与加强

一.    基础回顾 1   集合 1.1  集合的类型与各自的特性 ---|Collection: 单列集合 ---|List: 有存储顺序, 可重复 ---|ArrayList:    数组实现, 查找快, 增删慢 由于是数组实现, 在增和删的时候会牵扯到数组 增容, 以及拷贝元素. 所以慢.数组是可以直接按索引查找, 所以查找时较快 ---|LinkedList:   链表实现, 增删快, 查找慢由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个元素, 后

Java基础回顾(上)

一.唠叨 有朋友开始接触Java,问我一些基础的问题,突然发现不知该如何回答,十分尴尬.痛定思痛,便回炉重造,将java基础的知识重新梳理了一遍. 以下是我看书时或摘要.或总结的语言,完全是Java中基础的基础. 二.学习笔记 (一)基本数据类型 1.标识符区分大小写:hello与Hello是不同的标识符. 2.基本数据类型的精度由低到高依次为:byte short char int long float double 3.格式控制符号: %d int类型 %c char类型 %f 浮点类型 %

java基础回顾之IO

Java的IO 是Java运用重要部分之一,涉及到的内容也比较多,容易混淆,一段时间不用,可能就会遗忘,要时常回顾记忆一下: (图片来源于网络) Java 流在处理上分为字符流和字节流. 字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组.Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他编码的字符流和 java 内 Unicode 字符流之间的转换.类 InputStreamRead

[Java基础回顾]Tomact及Http 部分总结.

前言:   刚好今天回来的很早, 总结下 Tomcat及Http的基础知识. 1, Tomcat    web相关概念        web:网页的意思,网页资源包括服务器上的所有资源.            web资源分类:                静态的资源:内容不会发生改变的资源                动态的资源:内容可能发生改变的资源            web技术:                静态的web技术:html css js 等               

Java基础复习(六)

1. 接口的实现类中的实现接口中的抽象方法的方法必须为public,为什么? 接口中所有的方法与变量都默认是 public 的,在接口中可以不写出来.但在实现类中,如果不明写的话,就变成了 friend  的了,也就是 “包访问权限”.而JAVA又规定,在实现接口或者覆写父类方法时,不能降低父类方法的访问权限,但是可以提高.也就是可以按照  friend protected public 来提高访问权限,但不能按照 public protected friend 来降低访问权限. 反证法: 接口

5.JAVA基础回顾

java有什么特点? 1.简单性 2.面向对象的语言 3.一种与平台无关的语言(可跨平台) 4.健壮性和安全性 5.多线程 6.垃圾回收机制 2.什么是JDK?什么是JRE? JDK是JAVA的开发工具集.(编译环境,运行环境,调试环境,基础类库) JRE是JAVA的运行环境. (虚拟机,核心类库以及连接文件:JDK包括JRE) 3.JDK的目录结构是怎样的? bin:存放可执行的命令文件.javac.exe为编译的可执行文件: java.exe为执行java的可执行文件. db:数据库支持目录