ThreadPoolExecutor
线程池
好处:
降低资源的消耗。线程本身就是一种资源。创建和销毁线程会有CPU开销。创建的线程也会占用一定的内存。
提高任务执行的响应速度,执行任务时可以不必等到线程创建完之后在执行。
提高线程的可管理性,线程不能无限的创建,需要进行统一的分配调优监控。
不适用线程池的话,频繁的线程创建和销毁会占用更多的cpu和内存。频繁的线程创建和销毁会对gc产生比较大的压力。线程太多,线程间切换带来的开销将不可忽视,线程太少,多核cpu得不到充分利用,是一种浪费。
可以看出合理使用的线程池是多么重要的事情。
先从线程池的构造函数看起(这里找了个最多参数的):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public ThreadPoolExecutor(int corePoolSize, // 1 int maximumPoolSize, // 2 long keepAliveTime, // 3 TimeUnit unit, // 4 BlockingQueue<Runnable> workQueue, // 5 ThreadFactory threadFactory, // 6 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; }
|
序号 |
名称 |
类型 |
含义 |
1 |
corePoolSize |
int |
线程池里的核心线程数量 |
2 |
maximumPoolSize |
int |
线程池里允许有的最大线程数量 |
3 |
keepAliveTime |
long |
线程最大空闲等待时间 |
4 |
unit |
TimeUnit |
时间单位分时秒 |
5 |
workQueue |
BlockingQueue Runable |
线程等待队列 |
6 |
threadFactory |
ThreadFactory |
线程创建工厂 |
7 |
handler |
RejectedExecutionHandler |
拒绝策略 |
corePoolSize
线程池里面的核心线程池,这里面的线程是并行的,并行和并发是两个概念,并发是CPU切换的速度快到人们感受不到所以认为任务是在一起允许。而并行则是真正的在一起执行,这需要我们的CPU拥有多个核心才行。比如我的电脑是8核16线程,则代表我的这台电脑在同一时间可以并行允许16个线程。这里有个Demo可以自己跑起来看下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public class ThreadPoolDemo { public static void main(String[] args) { ThreadPoolDemo threadPoolDemo = new ThreadPoolDemo(); threadPoolDemo.doPricess(); } void doPricess(){ ExecutorService executorService = null; executorService = new ThreadPoolExecutor(16, 16,60, TimeUnit.SECONDS,new LinkedBlockingDeque<>()); for(int i=0;i<40;i++){ TestPoolThreadRunnable thread = new TestPoolThreadRunnable(i); executorService.execute(thread); } executorService.shutdown(); } class TestPoolThreadRunnable implements Runnable{ Integer count; TestPoolThreadRunnable(Integer count){ this.count = count; } @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count++ +" "+ Thread.currentThread().getId()); } } }
|
触发问题:java.util.concurrent.RejectedExecutionException:这个错误的意思就是往线程池里面提交的任务被拒绝了。那什么情况下会出现线程被线程池拒绝呢?
- 当线程等待队列用的是有限的比如
SynchronousQueue
这个队列,当我们的核心线程满了,然后队列也满了然后运行的最大线程数量也就是(maximumPoolSize)也满了,这个时候就会报RejectedExecutionException
奔溃。
- 当线程池显示的调用了shutDown方法后,线程池又去提交了任务,这个时候就会报这个错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class ThreadPoolDemo { public static void main(String[] args) { ThreadPoolDemo threadPoolDemo = new ThreadPoolDemo(); try { threadPoolDemo.doPricess(); } catch (InterruptedException e) { e.printStackTrace(); } } ExecutorService executorService = null; void doPricess() throws InterruptedException { executorService = new ThreadPoolExecutor(5, 8,60, TimeUnit.SECONDS,new LinkedBlockingDeque<>()); for(int i=0;i<40;i++){ TestPoolThreadRunnable thread = new TestPoolThreadRunnable(i); executorService.execute(thread); executorService.shutdown(); } } class TestPoolThreadRunnable implements Runnable{ Integer count; TestPoolThreadRunnable(Integer count){ this.count = count; } @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(count++ +" "+ Thread.currentThread().getId()+" "+System.currentTimeMillis()); } } }
|