文章目录
更多关于Java并发编程的文章请点击这里:Java并发编程实践(0)-目录页
在上文中已经写过Executor线程调度框架的使用及几种线程池,它们是整个Java并发编程的核心内容;本文将继续讲解和Executor一样重要的自定义线程池,它能让我们自己去定义一个多线程的执行者拥有的线程核心数、最大线程数、空闲线存活时间等。
本篇总结自《Java并发编程实践》第八章 应用线程池 ,以及相关博客,想要更加深入了解的同学建议阅读该书。
一、什么是ThreadPoolExecutor
ThreadPoolExecutor位于java.util.concurrent并发包下,为一些Executor提供了基本的实现,在JDK1.5中由Executors中的工厂中的newCachedThreadPool、newFixedThreadPool和newScheduledThreadExecutor方法所返回。但在JDK1.7之后,不能通过Executors去获得ThreadPoolExecutor了,而是需要自己手动去定制。ThreadPoolExecutor是一个灵活的、健壮的池实现,允许用户进行各种各样的定制。
二、ThreadPoolExecutor构造方法参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,//可不设置
RejectedExecutionHandler handler//可不设置)
- core线程还能应付的,则不断的创建新的线程,但不会超出corePoolSize;
- core线程无法应付,则将任务扔到队列里面,并且用core线程去执行;
- 工作队列满了(意味着插入任务失败),则开始创建MAX线程,线程数达到MAX后,队列还一直是满的,则抛出RejectedExecutionException。
2.1、corePoolSize
核心线程池大小,当线程池中的线程数目小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
2.1、maximumPoolSize
最大线程池大小,表示当前池中可以活跃的最大线程数目。
2.3、keepAliveTime
线程池中超过corePoolSize数目的空闲线程最大存活时间。
2.4、TimeUnit
keepAliveTime时间单位。可以设置为TimeUnit.MICROSECONDS
、TimeUnit.SECONDS
等单位,分别表示毫秒和秒。
2.5、workQueue
阻塞任务队列,用以存储超出了corePoolSize的线程。
2.6、threadFactory
新建线程工厂。如果没有的话则使用系统默认的。
2.7、RejectedExecutionHandler
当提交任务数超过maxmumPoolSize与workQueue之和时,任务会交给RejectedExecutionHandler来处理。如果没有的话则使用系统默认的。
三、使用自己构造的ThreadPoolExecutor
测试类:
public class ThreadPoolExecutorDemo {
@Test
public void testThreadPoolExecutor(){
ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
10,
1000,
TimeUnit.MICROSECONDS,
new ArrayBlockingQueue<Runnable>(3),
new MyThreadFactory(),
new MyRejectedExecutionHandler());
for (int i = 0; i < 35; i++) {
int count = i;
executor.execute(new Runnable() {
@Override
public void run() {
//模拟耗时操作
for (int j = 0; j < 500000; j++) {
//..
}
System.out.println("这是第"+count+"个线程在执行任务----"+Thread.currentThread().getName());
}
});
}
}
}
自定义的线程工厂类:
public class MyThreadFactory implements ThreadFactory {
//线程标识器
private AtomicInteger count = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
//标识器自增1
count.incrementAndGet();
Thread thread = new Thread(r, "自定义线程(" + count + ")");
return thread;
}
}
自定义的异常处理类:
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
//对超出的线程任务进行处理
System.out.println("已处理...");
}
}
执行后发现,当循环过多时,需要同时活跃的线程大于5个之后,新产生的线程进入阻塞队列中,当需要同时活跃的线程大于10个之后,新产生的线程将被自定义的MyRejectedExecutionHandler 处理。