1.线程池
使用享元模式 从池子里面获取对象,没有就创建,比较动态,节约资源。
列如 jdbc连接池
jdk创建线程池几种方式
ExecutorService executorService1 = Executors.newCachedThreadPool();//可缓存线程池
executorService1.execute(new Runnable() {
@Override
public void run() {
System.out.println();
}
});
ExecutorService executorService2 = Executors.newSingleThreadExecutor();//单例线程池
ExecutorService executorService3 = Executors.newFixedThreadPool(1);//指定数量线程池
ScheduledExecutorService executorService4 = Executors.newScheduledThreadPool(10);//可定时
executorService4.schedule(()->{},1L, TimeUnit.SECONDS);
底层都是使用:new ThreadPoolExecutor()
线程池七大参数
public ThreadPoolExecutor(int corePoolSize, //核心线程大小
int maximumPoolSize, //线程池最大线程数量
long keepAliveTime, //多余的空闲线程存活时间
TimeUnit unit, //空闲线程存活时间单位
BlockingQueue<Runnable> workQueue, //工作队列
ThreadFactory threadFactory, //线程工厂
RejectedExecutionHandler handler) //拒绝策略
AbortPolicy:丢弃任务并抛出 RejectedExecutionException 异常。(默认这种)
DiscardPolicy:丢弃任务,但是不抛出异常
DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) 。也就是当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务从队尾添加进去,等待执行。
CallerRunsPolicy:谁调用,谁处理。由调用线程(即提交任务给线程池的线程)处理该任务,如果线程池已经被shutdown则直接丢弃 同步方式运行
线程池原理:
1.线程池准备好,core核心线程开始接受任务;
2.当core核心线程满了之后,再有任务进来就会放入阻塞队列里面,空闲的核心线程就会去阻塞队列里面获取任务执行;
3.当阻塞队列满了之后就会生成新的线程,最大达到maximumPoolSize;
4.超过核心线程的空闲线程会在keepAliveTime时间周期内被销毁掉,最终保留corePoolSize线程数量。
5.如果达到最大线程maximumPoolSize数量还有任务,就会执行拒绝策略。
不建议使用jdk自带的创建线程池方法,一般自行构造。
1.workQueue工作队列使用无界队列(没有设置固定大小的队列),容易内存泄漏
2.最大线程为Integer.MAX_VALUE,无限创建线程