本文作者:黄海燕,叩丁狼高级讲师。原创文章,转载请注明出处。
1.1 为什么要使用线程池?
所谓线程池,其实和连接池的概念很像,就是在内存中实现创建好了多个线程,我们使用的时候直接从里面拿,不用的时候直接放回去,并且线程池我们是可以进行管理的,很好的控制多个线程,并且减少了创建和销毁的过程减小了内存中的消耗。
相比起普通的创建线程,线程池的好处:
- 重用存在的线程,减少对象创建、消亡的开销,性能佳。
- 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
- 提供定时执行、定期执行、单线程、并发数控制等功能。
1.2 线程池常用类体系结构:
1.3 ThreadPoolExecutor类
Executor接口表示线程池,而ThreadPoolExecutor为Executor接口最常用的实现类。所以学线程池不能不先学习ThreadPoolExecutor。
ThreadPoolExecutor类中有四个公共的构造器,也就是我们可以通过访问构造器创建对象。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}
参数 | 参数描述 |
---|---|
int corePoolSize: | 表示允许线程池中允许同时运行的最大线程数。(线程池的核心池大小,在创建线程池之后,线程池默认没有任何线程。当有任务过来的时候才会去创建创建线程执行任务。换个说法,线程池创建之后,线程池中的线程数为0,当任务过来就会创建一个线程去执行,直到线程数达到corePoolSize 之后,就会被到达的任务放在队列中。) |
int maximumPoolSize: | 线程池允许的最大线程数,他表示最大能创建多少个线程。maximumPoolSize肯定是大于等于corePoolSize。 |
long keepAliveTime: | 表示线程没有任务时最多保持多久然后停止。默认情况下,只有线程池中线程数大于corePoolSize时,keepAliveTime才会起作用。换句话说,当线程池中的线程数大于corePoolSize,并且一个线程空闲时间达到了keepAliveTime,那么就是shutdown。 |
TimeUnit unit: | 约束keepAliveTime的时间单位,如:时、分、秒 |
BlockingQueue<Runnable> workQueue: | 一个阻塞队列,用来存储等待执行的任务,当线程池中的线程数超过它的corePoolSize的时候,线程会进入阻塞队列进行阻塞等待。通过workQueue,线程池实现了阻塞功能。阻塞队列选择:ArrayBlockingQueue;LinkedBlockingQueue;SynchronousQueue;PriorityBlockingQueue; |
ThreadFactory threadFactory: | 线程工厂,创建线程的对象 |
RejectedExecutionHandler handler: | 拒绝处理任务时的策略。 |
简单使用:
public class Demo {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(5,10,0,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(10));
for (int i = 0;i<50;i++){
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
pool.shutdown();
}
}
抛出异常:
报错原因是因为最大线程数只有10,任务数为50,任务数>最大线程数据时线程池会启用拒绝策略,我们没有传入拒绝策略,所以使用了默认策略AbortPolicy。
拒绝策略:
ThreadPoolExecutor内部类 | 内部类的描述 |
---|---|
ThreadPoolExecutor.AbortPolicy |
|
ThreadPoolExecutor.DiscardPolicy |
|
ThreadPoolExecutor.DiscardOldestPolicy |
|
ThreadPoolExecutor.CallerRunsPolicy |
|
1.4使用Executors创建创建线程池Executors线程池工具类,提供了一系列静态工厂方法用于创建各种线程池。列表如下:
方法名 | 方法描述 |
---|---|
newFixedThreadPool(int nThreads) |
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 |
newWorkStealingPool(int parallelism) |
创建持有足够线程的线程池来支持给定的并行级别,并通过使用多个队列,减少竞争,它需要穿一个并行级别的参数,如果不传,则被设定为默认的CPU数量。ForkJoinPool支持大任务分解成小任务的线程池 |
newSingleThreadExecutor() |
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行**** |
newCachedThreadPool() |
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。线程可以重复利用执行任务。默认为60s未使用就被终止和移除 |
newSingleThreadScheduledExecutor() |
创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。 |
newScheduledThreadPool(int corePoolSize) |
创建一个定长线程池,支持定时及周期性任务执行。 |
想获取更多技术干货,请前往叩丁狼官网:http://www.wolfcode.cn/all_article.html