线程池
1.概念
- 如果有非常多的任务需要很多的线程来完成,每个线程的工作时间不长,就需要创建很多的线程,工作完会立即销毁,出现的情况是线程的频繁的创建和销毁。造成大量的资源 的浪费。
- 线程池是可以创建一些线程,放在池子中,用的时候去池子取一个线程取使用,使用完成之后再放回去,线程可以重复的使用。
- 线程池的底层实际上就是集合队列,里面存储的线程对象,用的时候去抽取就可以了,就不用频繁的创建线程了。
- 优点:能够尽可能的减少在创建和销毁线程上所花费的时间以及系统资源的浪费开销。解决资源不足的问题,如果不使用线程池,有可能造成系统创建大量同类线程而导致的消耗完内存或者过度切换的问题。
- 将任务(Task)提交给线程池,通过线程池分配线程,运行任务,任务结束后,线程重新放入线程池中方便后续线程的使用
- 判断一个线程是否存活,判断其存活时间,如果线程单位时间内没有接触到任务,所以就可以将线程进行销毁操作。
2.线程池的引入
引入线程池的目的是为了解决,每次执行线程任务的时候,新的线程会被立即销毁,造成资源的浪费。所以引入线程池的概念,也既是创建的线程对象,在执行完线程任务之后,没有任务,会进入线程的等待的阶段,等待新的任务的到来,这样能够保证空闲线程来做任务,同时也不会造成资源浪费在创建和销毁线程身上。
3.线程池的创建
- Executor : 线程池的根接口,通过execute(Runnable task)执行任务
- ExecutorService :Executor 的子接口,通过submit(Runnable task)来提交任务,执行任务。
ThreadPoolExecutor
: ExecutorService的子实现类,通过submit(Runnable task) 来提交任务,执行任务Executors
: 执行器类(线程池工厂类),通过该类来获得不同特点的线程池对象类中有很多静态方法,直接调用就可以获得各种特点线程池对象。
2.1 线程池中常用的API
方法 | 类型 | 解释 |
---|---|---|
newFixedThreadPool(int Threads) | 固定大小线程池 | 池中包含固定数目的线程,空闲线程一直保留。只有核心线程,线程数量固定,任务队列为LinkedBlockingQueue |
newCachedThreadPool | 创建动态的线程池 | 无核心线程,非核心线程数量无限,执行完闲置60s后回收,任务队列SynchronousQueue |
newScheduledThreadPool | 可以执行定时任务的线程池 | 用于调度执行的固定线程池,执行定时或周期性任务。和弦线程数量固定,非核心线程数量无线,执行完闲置10ms后回收,任务队列为DelayedWorkQueue |
newSingleExecutor | 单线程 | 只有一个线程的线程池,会顺序执行所提交的任务 |
2.2 创建线程池
- 调用Executors类的静态反方,newCachedThreadPool
- 调用sumbit提交Runnable 或者 Callable对象
- 保存好返回的Future对象,以便能够得到结果或者取消任务
- 如果不想再提交任何任务,调用shutdown方法
// 代码实现
public class Demo2 {
public static void main(String[] args) {
/* 1. 调用Executors类的静态反方,newCachedThreadPool
2. 调用sumbit提交Runnable 或者 Callable对象
3. 保存好返回的Future对象,以便能够得到结果或者取消任务
4. 如果不想再提交任何任务,调用shutdown方法
*/
ExecutorService threadPool = Executors.newFixedThreadPool(10);
/*
* 通过使用匿名内部类实现线程任务的提交执行操作
*/
for (int i = 0; i < 10; i++) {
threadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"匿名内部类的执行操作");
}
});
threadPool.submit(()-> System.out.println(Thread.currentThread().getName()+"正在进行执行操作"));
}
threadPool.shutdown();
}
}
//线程池的运行结果
pool-1-thread-1匿名内部类的执行操作
pool-1-thread-2正在进行执行操作
pool-1-thread-3匿名内部类的执行操作
pool-1-thread-1匿名内部类的执行操作
pool-1-thread-2正在进行执行操作
pool-1-thread-1匿名内部类的执行操作
pool-1-thread-2正在进行执行操作
pool-1-thread-1匿名内部类的执行操作
pool-1-thread-2正在进行执行操作
pool-1-thread-1匿名内部类的执行操作
pool-1-thread-1匿名内部类的执行操作
pool-1-thread-1正在进行执行操作
pool-1-thread-2正在进行执行操作
pool-1-thread-4正在进行执行操作
pool-1-thread-5匿名内部类的执行操作
pool-1-thread-6正在进行执行操作
pool-1-thread-7匿名内部类的执行操作
pool-1-thread-8正在进行执行操作
pool-1-thread-9匿名内部类的执行操作
pool-1-thread-10正在进行执行操作
2.3 对于线程池资源的关闭
线程池中的资源关闭,有两种:
- shutdown :当使用完一个线程池的时候,调用shutdown的反方,该方法启动时,线程池的关闭序列被关闭的执行器,不再接收新的任务,当所有的任务都完成的时候,线程池中的所有的线程死亡。
- shutdownNow :表示的是线程池会取消所有尚未开始的任务。
3. 线程池的执行流程
语言叙述
:线程池的线程的概念,实际上就是公司中的老员工和临时工,核心的线程就是公司中的老员工,非核心线程就是公司中的临时工。任务队列进入的时候,首先是通过核心线程进行执行的操作,如果核心线程未满,则创建线程进行执行,如果已经满了,判断此时的任务队列是否满,如果足够的不满,则添加任务到任务队列进行排队的操作,如果已经满了,看看线程是否达到最大值,如果是的话,执行拒绝策略,如果不是则创建非核心的线程执行任务,也就是找临时工进行工作的处理。
---------------未完结待补充。