线程池可以减少每个任务调用的开销,也就是减少单个任务的等待时间.当使用单线程时,任务需要进行排队,在线程池中,每个任务都有自己的线程,不再排队,实现多任务同时处理.
java.util.concurrent.ThreadPoolExecutor的常用构造方法如下:
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue
RejectedExecutionHandler handler)
corePoolSize: 线程池维护线程的最少线程数,也是核心线程数,包括空闲线程
maximumPoolSize: 线程池维护线程的最大线程数
keepAliveTime: 线程池维护线程所允许的空闲时间
unit: 程池维护线程所允许的空闲时间的单位
workQueue: 线程池所使用的缓冲队列
handler: 线程池对拒绝任务的处理策略
任务通过execute(Runnable)方法添加到线程池,一个任务就是一个Runnable对象,任务的执行就是Runnable对象的run()方法.
当一个任务将被添加到线程池中时:
如果当前线程数小于corePoolSize,即使有空闲线程,也会创建新的线程来处理新增任务;
如果当前线程数等于corePoolSize,如果缓冲队列未满,该任务被放入缓冲队列;
如果当前线程数大于corePoolSize,且冲队列已满,如果当前线程数小于maximumPoolSize, 就创建新的线程来处理新增任务;
如果当前线程数等于maximumPoolSize,且冲队列已满,将会使用handler所指定的策略来处理任务.
线程池处理任务的顺序是:
核心线程corePoolSize, 缓冲队列workQueue, 最大线程maximumPoolSize
当前线程数大于corePoolSize,线程池中的空闲线程在超过keepAliveTime, 会自动终止.线程池通过keepAliveTime来动态维护线程数.
unit的可选参数是java.util.concurrent.TimeUnit类中的
MICROSECONDS MILLISECONDS NANOSECONDS SECONDS
workQueue的参数有:
java.util.concurrent.ArrayBlockingQueue,该队列的长度有限制
java.util.concurrent.LinkedBlockingQueue,该队列的长度没有限制
建议使用ArrayBlockingQueue
handler的可选参数有:
ThreadPoolExecutor.AbortPolicy 抛出 RejectedExecutionException.
static class ThreadPoolExecutor.CallerRunsPolicy 重试添加当前任务,会重复调用execute();
static class ThreadPoolExecutor.DiscardOldestPolicy 放弃最旧的任务,然后重试 execute()方法;
static class ThreadPoolExecutor.DiscardPolicy 放弃当前任务.
示例代码:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestExecutor {public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 300, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(3),
new ThreadPoolExecutor.CallerRunsPolicy()
);
for (int i=1; i<15; i++){
executor.execute(new Task(i));
}
executor.shutdown();
}
}class Task implements Runnable{
public Task(int num){
this.num = num;
}
public void run() {
System.out.println("任务名称="+"taskName"+num);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private int num;
}
ThreadPoolExecutor除了execute()方法外,还有afterExecute(),beforeExecute(),
另外,可以对ThreadPoolExecutor重写受保护的方法进行扩展.