# 1、线程池
### 1 为什么要使用线程池
平常使用new Thread(). start( ) 的方式启动的线程,使用完之后就会变成垃圾,被系统销毁掉;如果在任务众多的情况下频繁的开启和销毁线程,就会给系统造成极大的压力;而使用线程池则会对线程进行统一的管理,一个线程在执行完任务后不会被系统回收,而是可以继续执行下一个任务,不会造成线程的频繁启动和销毁,减轻了系统的压力。
### 2 Java中的线程池
#### 1 ThreadPoolExecutor 基本线程池
~~~
public ThreadPoolExecutor(int corePoolSize, //该线程池中的核心线程数量
int maximumPoolSize, //该线程中的最大线程数量
long keepAliveTime, //该线程的非核心线程的存活时间(可设置allowCoreThreadTimeOut=true,使超时时间适用于核心线程)
TimeUnit unit, //存活时间的单位 有:纳秒,毫秒,微秒,秒,分支,小时,天
BlockingQueue<Runnable> workQueue, //任务队列
ThreadFactory threadFactory, //线程工程,可用于设置线程的名字等属性,一般不使用
RejectedExecutionHandler handler //
) {
...
}
~~~
#### 2 线程池的执行策略
当execute( ) 一个任务时:
1. 当**核心线程未满时**,直接启动一个空闲的核心线程去执行任务;
2. 当**核心线程已满而任务队列未满时**,则将任务放在任务队列中,等待某个核心线程执行完任务后执行该任务;
3. 当**核心线程已满并且任务队列也已经满了时**,则启动一个空闲的非核心线程去执行任务;
4. 当**三者(核心线程,任务队列,非核心线程,也可以是最大线程数量和任务队列)均已满**,则会采取饱和策略,拒绝执行该任务,抛出异常 java.util.concurrent.RejectedExecutionException
#### 3 Java中内置的线程池
* **FixedThreadPool( )**
线程数量固定,且全部为核心线程,阻塞队列无界
**适用:执行长期的任务,性能较好**
~~~
//源码
public static ExecutorService newFixedThreadPool(int coreSize) {
return new ThreadPoolExecutor(coreSize, coreSize, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
}
//创建fixed线程池
final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
fixedThreadPool.execute(runnable);
~~~
* **CachedThreadPool( )**
没有核心线程,全部为非核心线程,最大线程数量为Integer.MAX\_VALUE,线程存活时间为60s
**适用:执行很多短期异步的小程序或者负载较轻的服务器**
~~~
//源码
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue());
}
//创建Cached线程池
final ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(runnable);
~~~
* **ScheduledThreadPool( )**
定时延时执行
**适用:周期性执行任务的场景**
~~~
//源码
public static ScheduledExecutorService newScheduledThreadPool(int coreSize) {
return new ScheduledThreadPoolExecutor(coreSize);
}
//创建Scheduled线程池
final ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
scheduledThreadPool.schedule(runnable,10,TimeUnit.SECONDS);//延迟启动任务
scheduledThreadPool.scheduleAtFixedRate(runnable,5,1,TimeUnit.SECONDS);//延迟5s后启动,每1s执行一次
scheduledThreadPool.scheduleWithFixedDelay(runnable,5,1,TimeUnit.SECONDS);//启动后第一次延迟5s执行,后面延迟1s执行
~~~
* **SingleThreadPool( )**
线程池中只要一个核心任务
**适用:一个任务一个任务执行的场景**
~~~
//源码
public static ExecutorService newSingleThreadExecutor() {
return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));
}
//创建Single线程池
final ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
singleThreadExecutor.execute(runnable);
~~~
* **SingleScheduledThreadPool( )**
只有一个核心线程的延时任务
~~~
//源码
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new Executors.DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1));
}
~~~
| | |
| --- | --- |
| | |
### 3 Java中的阻塞队列
| **队列名称** | **描述** |
| --- | --- |
| **ArrayBlockingQueue** | **一个由数组结构组成的有界阻塞队列。** |
| **LinkedBlockingQueue** | **一个由链表结构组成的有界阻塞队列。** |
| **PriorityBlockingQueue** | **一个支持优先级排序的无界阻塞队列。** |
| **DelayQueue** | **一个使用优先级队列实现的无界阻塞队列。** |
| **SynchronousQueue** | **一个不存储元素的阻塞队列。** |
| **LinkedTransferQueue**| **一个由链表结构组成的无界阻塞队列。** |
| **LinkedBlockingDeque** | **一个由链表结构组成的双向阻塞队列。** |