池化技术
简单来说,所有的池化技术就是提前保留大量的资源,以备不时之需
池化技术举例
-
线程池
-
数据库连接池
等
池化技术特点
- 核心数量对象
- 最大数量对象
- 非核心对象数量
- 非核心对象的生命周期
池化技术优点
- 对象复用,减少对象创建、销毁的时间
- 资源重用性
- 更快的系统响应速度
- 新的资源分配手段
- 统一的管理,避免出现内存泄漏
线程池
JDK1.5之后,java提供了创建线程池的工具类 (java.util.concurrent.Executors)
Executors提供的静态方法
Executors类的静态方法 | 默认参数 |
---|---|
newCachedThreadPool() | 有任务时才创建线程,空闲线程被保留1分钟 |
newFixedThreadPool(int nThreads) | 线程池中包含固定数目的线程,空闲线程会被一直保留。参数nThreads设定线程池中线程的数目 |
newScheduledThreadPool(int corePoolSize) | 线程池能按时间计划来执行任务,它允许用户设置执行计划运行的时间。参数corePoolSize设置线程池中线程的最小数目。当任务较多,线程池可能会创建更多的工作线程来执行任务 |
newSingleThreadExecutor() | 线程池中只有一个工作线程,它依次执行每个任务 |
newSingleThreadScheduledExecutor() | 线程池中只有一个工作线程,它能按照时间定时的来执行任务 |
线程池常用的方法
submit方法:
submit方法会提交一个任务给线程池执行,该任务可以是返回结果的Callable任务,或者不带返回值的Runnable任务(此时一开始的指定结果为null),通过Fature可以来获得提交到线程池的任务的返回值。submit提交任务以及运行过程如下:
- 向线程池中提交一个Runnable或者Callable任务
- 将任务作为参数使用newTaskFor方法构造出FatureTask
- 通过FatureTask的get方法来获取结果
shutdown方法:
shutdown方法作用是向线程池发送关闭的指令,一旦线程池调用了shudown方法之后,线程池就不能在接受其他任务了(原来执行的任务或者在任务队列里面的任务还能正常执行),如果此时仍然向线程池中提交任务,则会抛出RejectedExecutionException异常。
shutdownNow方法:
与shutdown不同,shutdownNow会立即关闭线程池 —— 当前在线程池中运行的任务会全部被取消
awaitTermination 方法:
awaitTermination 可以用来判断线程池是否已经关闭。调用 awaitTermination 之后,在 timeout 时间内,如果线程池没有关闭,则阻塞当前线程,否则返回 true;当超过 timeout 的时间后,若线程池已经关闭则返回 true,否则返回 false。该方法一般这样使用:
- 任务全部提交完毕之后,我们调用 shutdown 方法向线程池发送关闭的指令;
- 然后我们通过 awaitTermination 来检测到线程池是否已经关闭,可以得知线程池中所有的任务是否已经执行完毕;
- 线程池执行完已经提交的所有任务,并将自己关闭;
- 调用 awaitTermination 方法的线程停止阻塞,并返回 true;
isShutdown方法:
如果线程池已经调用shutdown或者shutdownNow,则立即返回true,否则返回false;
ThreadPoolExecutor
newFixedThreadPool(int nThreads)中底层的为ThreadPoolExecutor,ThreadPoolExecutor中重要的参数
- corePoolSize :核心线程池数量
- maximumPoolSize: 最大线程数量
- 线程池数量 + 核心以外的数量
- 如果任务队列满了,并且池中线程数小于最大线程池并且大于核心线程池数量,会在创建新的线程执行任务
- keepAliveTime: 核心池以外的线程存活时间,即没有任务的外包的存活时间
- 如果给线程池设置 allowCoreThreadTimeOut(true),则核心线程在空闲时头上也会响起死亡的倒计时
- 如果任务是多而容易执行的,可以调大这个参数,那样线程就可以在存活的时间里有更大可能接受新任务
- workQueue: 保存待执行任务的阻塞队列
- threadFactory: 每个线程创建的地方
- 可以给线程起个好听的名字
- handler : 拒绝策略
- CallerRunsPolic:只要线程池没关闭,就直接用调用者所在线程来运行任务
- AbortPolicy:直接抛出 RejectedExecutionException 异常(默认)
- DiscardPolicy:悄悄把任务放生,不做了
- DiscardOldestPolicy:把队列里待最久的那个任务扔了,然后再调用 execute()试试我们也可以实现自己的 RejectedExecutionHandler接口自定义策略,比如如记录日志什么的