线程池的意义
1.线程池控制线程并发数:并发线程,就是n个线程在运行中,不是指时间上同时运行,如果过多线程抢夺CPU,会导致CPU资源不足而阻塞(为什么会这样,不需要理会)。
2.创建和销毁时间如果大于运行时间,那么开启线程很不划算,线程池也是解决这个问题,相当于复用机制。
3.线程池由任务队列和工作线程组成,它可以重用线程来避免线程创建的开销,在任务过多时通过排队避免创建过多线程来减少系统资源消耗和竞争,确保任务有序完成
ThreadPoolExecutor类
- 通常得到线程池后会调用其中的 submit 或 execute 方法去提交执行异步任务,其实 submit 方法最终会调用 execute 方法来进行操作,只是他提供了一个 Future 来托管返回值的处理而已,当你调用需要有返回值的信息时用它来处理是比较好的,这个 Future 会包装 Callable 信息。
- ScheduledThreadPoolExecutor 是基于 ThreadPoolExecutor 实现的,其调用线程池的构造使用了 DelayedWorkQueue 阻塞队列实现而已。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
1. corePoolSize:核心运行的线程个数,也就是当超过这个范围的时候就需要将新的异步任务放入到等待队列中,小于
这个数时添加进来的异步任务一般直接新建 Thread 执行;
2. maximumPoolSize:最大线程个数,当大于了这个值就会将准备新加的异步任务由一个丢弃处理机制来处理,大于
corePoolSize 且小于 maximumPoolSize 则新建 Thread 执行,但是当通过 newFixedThreadPool 创建的时候,
corePoolSize 和 maximumPoolSize 是一样的,而 corePoolSize 是先执行的,所以他会先被放入等待队列而不会
执行到下面的丢弃处理中;
3. workQueue:任务等待队列,当达到 corePoolSize 的时候就向该等待队列放入线程信息(默认为一个LinkedBlockingQueue);
4. keepAliveTime:默认是 0,当线程没有任务处理后空闲线程保持多长时间,不推荐使用;
5. threadFactory:是构造 Thread 的方法,一个接口类,可以使用默认的 default 实现,也可以自己去包装和传递,
主要实现 newThread 方法即可;
6. handler:当参数 maximumPoolSize 达到后丢弃处理的方法实现,java 提供了 5 种丢弃处理的方法,当然你也可以自己弄,
主要是要实现接口 RejectedExecutionHandler 中 rejectedExecution(Runnabler, ThreadPoolExecutor e) 方法,
java 默认使用的是 AbortPolicy,他的作用是当出现这种情况的时候抛出一个异常;
// 创建固定线程数(都是核心线程)的线程池,可控制最大并发数(就是传入的参数)且可重用(都是核心线程),超出的线程会在队列中等待
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
//1.8引入,创建持有足够线程的线程池来支持给定的并行级别,并通过使用多个队列减少竞争,它需要穿一个并行级别的参数,如果不传则被设定为默认的CPU数量。
public static ExecutorService newWorkStealingPool(int parallelism) {
return new ForkJoinPool
(parallelism,
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
// 创建只有一个核心线程的线程池,超出的线程会在队列中等待
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
// 创建无核心线程,只有最大线程数的线程池,无核心线程即无复用(都是新new的线程),线程会被回收。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}