1.先看构造方法
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.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
各个参数的含义:
/** * corePoolSize 核心线程池大小 * maximumPoolSize 最大线程池大小 * keepAliveTime 线程最大空闲时间 * unit 时间单位 * workQueue 线程等待队列 * threadFactory 线程创建工厂 * handler 拒绝策略 */
2.运行机制
当任务加进来之后,先创建核心线程数执行任务;当大于核心线程数时;它会把任务添加到工作队列中,同时开始创建新的线程来执行任务;当总线程数超过最大线程数时;就会交给handler来处理,一般会被拒绝。
3.看一个例子
package com.ysl.rxjava;
import sun.util.calendar.CalendarSystem;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPoolTest {
public static void main(String[] args) throws InterruptedException, IOException {
int corePoolSize = 2;
int maximumPoolSize = 3;
long keepAliveTime = 10;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
ThreadFactory threadFactory = new NameTreadFactory();
RejectedExecutionHandler handler = new MyIgnorePolicy();
/**
* corePoolSize 核心线程池大小
* maximumPoolSize 最大线程池大小
* keepAliveTime 线程最大空闲时间
* unit 时间单位
* workQueue 线程等待队列
* threadFactory 线程创建工厂
* handler 拒绝策略
*/
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
workQueue, threadFactory, handler);
executor.prestartAllCoreThreads(); // 预启动所有核心线程
Thread.sleep(2000);
for (int i = 1; i <= 2; i++) {
MyTask task = new MyTask(String.valueOf(i));
executor.execute(task);
System.out.println(i+",workQueue.size:"+workQueue.size());
}
System.in.read(); //阻塞主线程
}
static class NameTreadFactory implements ThreadFactory {
private final AtomicInteger mThreadNum = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "my-thread-" + mThreadNum.getAndIncrement());
System.out.println(t.getName() + " has been created");
return t;
}
}
public static class MyIgnorePolicy implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
doLog(r, e);
}
private void doLog(Runnable r, ThreadPoolExecutor e) {
// 可做日志记录等
System.err.println( r.toString() + " rejected");
// System.out.println("completedTaskCount: " + e.getCompletedTaskCount());
}
}
static class MyTask implements Runnable {
private String name;
public MyTask(String name) {
this.name = name;
}
@Override
public void run() {
try {
System.out.println(this.toString() + " is running!");
Thread.sleep(10000); //让任务执行慢点
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String getName() {
return name;
}
@Override
public String toString() {
return "MyTask [name=" + name + "]";
}
}
}
自己创建的线程池;核心线程2;工作队列2;总线程数是3;
当for循环一次和两次时:
核心线程就够用了,不会创建第三个线程了。
当for循环三次或四次时:
核心线程数 + 队列大小刚好可以放下;所以3、4号任务放到了工作队列里;等待执行;当1、2执行完了,开始执行3、4.
当for循环5次时:
可以看到1、2执行了,3、4进入队列了,最后等1、2执行完了才执行;又创建了一个3号线程,并且立马执行了5号任务;
当执行6次及以上:
可以发现,前面和循环5次一样;第六次没有执行而是直接被拒绝了;因为线程数达到了最大数量,而且都在使用;工作队列也是满的;此时就交给handler处理了。handler里面拒绝处理任务。