ThreadPoolExecutor机制 
一、概述 
1、ThreadPoolExecutor作为java.util.concurrent包对外提供基础实现,以内部线程池的形式对外提供管理任务执行,线程调度,线程池管理等等服务; 
2、Executors方法提供的线程服务,都是通过参数设置来实现不同的线程池机制。 
3、先来了解其线程池管理的机制,有助于正确使用,避免错误使用导致严重故障。同时可以根据自己的需求实现自己的线程池

二、核心构造方法讲解 
下面是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;
}

构造方法参数讲解

参数名 作用
corePoolSize 核心线程池大小
maximumPoolSize 最大线程池大小
keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)使得核心线程有效时间
TimeUnit keepAliveTime时间单位
workQueue 阻塞任务队列
threadFactory 新建线程工厂
RejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理

重点讲解: 
其中比较容易让人误解的是:corePoolSize,maximumPoolSize,workQueue之间关系。

1.当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。 
2.当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行 
3.当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务 
4.当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理 
5.当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程 
6.当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

线程管理机制图示: 

三、Executors提供的线程池配置方案

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);
}

四、定制属于自己的线程池

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; public class CustomThreadPoolExecutor { private ThreadPoolExecutor pool = null; /**
* 线程池初始化方法
*
* corePoolSize 核心线程池大小----10
* maximumPoolSize 最大线程池大小----30
* keepAliveTime 线程池中超过corePoolSize数目的空闲线程最大存活时间----30+单位TimeUnit
* TimeUnit keepAliveTime时间单位----TimeUnit.MINUTES
* workQueue 阻塞队列----new ArrayBlockingQueue<Runnable>(10)====10容量的阻塞队列
* threadFactory 新建线程工厂----new CustomThreadFactory()====定制的线程工厂
* rejectedExecutionHandler 当提交任务数超过maxmumPoolSize+workQueue之和时,
* 即当提交第41个任务时(前面线程都没有执行完,此测试方法中用sleep(100)),
* 任务会交给RejectedExecutionHandler来处理
*/
public void init() {
pool = new ThreadPoolExecutor(
10,
30,
30,
TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(10),
new CustomThreadFactory(),
new CustomRejectedExecutionHandler());
} public void destory() {
if(pool != null) {
pool.shutdownNow();
}
} public ExecutorService getCustomThreadPoolExecutor() {
return this.pool;
} private class CustomThreadFactory implements ThreadFactory { private AtomicInteger count = new AtomicInteger(0); @Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
String threadName = CustomThreadPoolExecutor.class.getSimpleName() + count.addAndGet(1);
System.out.println(threadName);
t.setName(threadName);
return t;
}
} private class CustomRejectedExecutionHandler implements RejectedExecutionHandler { @Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 记录异常
// 报警处理等
System.out.println("error.............");
}
} // 测试构造的线程池
public static void main(String[] args) {
CustomThreadPoolExecutor exec = new CustomThreadPoolExecutor();
// 1.初始化
exec.init(); ExecutorService pool = exec.getCustomThreadPoolExecutor();
for(int i=1; i<100; i++) {
System.out.println("提交第" + i + "个任务!");
pool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("running=====");
}
});
} // 2.销毁----此处不能销毁,因为任务没有提交执行完,如果销毁线程池,任务也就无法执行了
// exec.destory(); try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

方法中建立一个核心线程数为30个,缓冲队列有10个的线程池。每个线程任务,执行时会先睡眠0.1秒,保证提交40个任务时没有任务被执行完,这样提交第41个任务是,会交给CustomRejectedExecutionHandler 类来处理。

http://825635381.iteye.com/blog/2184680

JAVA进阶----ThreadPoolExecutor机制(转)的更多相关文章

  1. JAVA进阶--ThreadPoolExecutor机制

    ThreadPoolExecutor机制 一.概述 1.ThreadPoolExecutor作为java.util.concurrent包对外提供基础实现,以内部线程池的形式对外提供管理任务执行,线程 ...

  2. JAVA进阶----ThreadPoolExecutor机制(转)

    http://825635381.iteye.com/blog/2184680 ThreadPoolExecutor机制 一.概述 1.ThreadPoolExecutor作为java.util.co ...

  3. Java进阶 | 泛型机制与反射原理

    一.泛型的概念 1.基础案例 泛型在Java中的应用非常广泛,最常见则是在集合容器中,先看下基础用法: public class Generic01 { public static void main ...

  4. Java进阶3. 内存回收机制

    Java进阶3. 内存回收机制 20131029 前言: 学过C++的都知道,C++中内存需要程序员自己维护.说道这里,很多开发的同学就感觉很痛苦,当他转向Java的时候,就会说你看Java多好啊,程 ...

  5. Java ExecutorService四种线程池及自定义ThreadPoolExecutor机制

    一.Java 线程池 Java通过Executors提供四种线程池,分别为:1.newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收 ...

  6. Java进阶之reflection(反射机制)——反射概念与基础

    反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...

  7. Java进阶(六)Java反射机制可恶问题NoSuchFieldException

    作为一种重要特性,Java反射机制在很多地方会用到.在此做一小结,供朋友们参考. 首先从一个问题开始着手. 可恶的问题又来了,NoSuchFieldException,如下图所示: 完全不知道这个qu ...

  8. Java 进阶7 并行优化 JDK多任务执行框架技术

    Java 进阶7 并行优化 JDK多任务执行框架技术 20131114          Java 语言本身就是支持多线程机制的,他提供了 Thread 类 Runnable 接口等简单的多线程支持工 ...

  9. Java进阶(五)Java I/O模型从BIO到NIO和Reactor模式

    原创文章,同步发自作者个人博客,http://www.jasongj.com/java/nio_reactor/ Java I/O模型 同步 vs. 异步 同步I/O 每个请求必须逐个地被处理,一个请 ...

随机推荐

  1. Apple严控Java太不人性化

    转自:http://www.cdtarena.com/javapx/201307/9115.html Apple为了在系统安全方面得到更好的声誉,对更容易造成系统漏洞的Java进行着严格的控制,并在自 ...

  2. FastReport 数据过滤

    FastReport 数据过滤 在DataBind 的 OnBeforePrint 设置条件   例:显示 大于0 的数据 procedure MasterData1OnBeforePrint(Sen ...

  3. php的var关键字

    public和var的作用差不多 因为 var定义的变量如果没有加protected 或 private则默认为public php4 中一般是用 varphp5 中就一般是用 public了 现在基 ...

  4. 【每日一摩斯】-Troubleshooting: High CPU Utilization (164768.1) - 系列5

    Oracle(用户)进程 以下这些操作都是需要消耗大量CPU资源的:解析大型查询,存储过程编译或执行,空间管理和排序. 下面这几篇文章可以帮助采集关于使用高CPU资源的进程的更多信息: Note:35 ...

  5. HDU 1425 sort 题解

    选择出数列中前k个最大的数. 这里由于数据特殊.所以能够使用hash表的方法: #include <cstdio> #include <algorithm> #include ...

  6. c# 调用外部exe程序

    c#调用外部exe程序,首先要 using System.Diagnostics; 然后开启一个新process System.Diagnostics.ProcessStartInfo p=null; ...

  7. 实现浏览器遗漏的原件 jQuery.selectCheckbox

    工作中遇到了一个下拉需要实现checkbox的效果,如下图 或许网上已经有实现了,但简单的功能自己实现就好了, 结构 <div class="form-control-wrap&quo ...

  8. Linux下SSH Session复制

    羡慕Windows下secureCRT的Session Copy功能,一直在寻找Linux下类似的软件,殊不知SSH本身就支持此功能. 特别感谢阿干同学的邮件分享. 详细方法 ? 1 2 3 4 Li ...

  9. javascript 中 事件流和事件冒泡

    一.事件流 是描述页面接受事件的顺序,IE 使用的是时间冒泡流;而Netscape的事件采用的是事件捕获流.1.事件冒泡JS 和 HTML是通过事件的方式实现交互.事件冒泡 开始元素,将事件逐级传递, ...

  10. 用js制作的几个效果

    一,表格光柱效果(奇偶行不同颜色,鼠标移上变色) <html xmlns="http://www.w3.org/1999/xhtml"><head>< ...