池化技术与线程池
池化技术与线程池
池化技术
简介
程序的运行,本质:占用系统的资源!优化资源的使用!=>池化技术
池化技术的应用:线程池、连接池、内存池、对象池...
一句话解释池化技术:事先准备好一些资源,有人要用就来我这里拿,用完之后还给我,下个人再过来用。
线程池的优点:
1.降低资源的消耗
2.提高响应速度
3.资源统一管理
线程复用,控制最大并发数、管理线程
线程池三大方法
newSingleThreadExecutor //单个线程运行
newFixedThreadPool //固定线程数运行
newCachedThreadPool //弹性线程数运行,可伸缩
package com.example.juc;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestExecutors {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor(); //单个线程运行
// ExecutorService threadPool = Executors.newFixedThreadPool(5); //固定线程数运行
// ExecutorService threadPool = Executors.newCachedThreadPool(); //弹性线程数运行,可伸缩
for (int i = 0; i < 100; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "");
});
}
threadPool.shutdown();
}
}
线程池七大参数
工作中不会使用以上三种方法,都是直接使用ThreadPoolExecutor来创建线程池
原因:
1.使用以上三种方法创建不安全
SingleThreadPool和FixedThreadPool方法允许请求队列长度为Integer.MAX_VALUE,可能会堆积大量请求,造成OOM
CachedThreadPool方法允许请求最大线程数为Integer.MAX_VALUE,可能会堆积大量请求,造成OOM
2.阿里巴巴开发者手册明确规定,使用ThreadPoolExecutor来创建线程池
源码分析:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
// ThreadPoolExecutor 参数定义
public ThreadPoolExecutor(int corePoolSize, // 核心线程池数量
int maximumPoolSize, // 最大线程池数量
long keepAliveTime, // 超过这个时间没有人调用就会将最大线程池中除了核心线程池的线程池释放
TimeUnit unit, // 超时时间单位
BlockingQueue<Runnable> workQueue, // 阻塞队列,类似等候区
ThreadFactory threadFactory, // 线程工厂,创建线程的,一般不用动
RejectedExecutionHandler handler // 拒接策略,在下一节详细讲) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
线程池四种拒绝策略
拒绝在 最大线程池数和阻塞队列都满了的时候,一个新的线程池待创建的时候发生
即 RejectedExecutionHandler 的四个实现类
AbortPolicy // 不处理新来的,抛出异常
CallerRunsPolicy // 把新来的打发走,哪来的回哪去
DiscardPolicy // 不处理新来的,丢掉线程,不抛异常
DiscardOldestPolicy // 尝试询问最老的线程是否处理完了,处理完了就处理新的,没处理完就丢掉新线程,不抛异常
package com.example.juc;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestRejectPolicy {
public static void main(String[] args) {
// ExecutorService pool = new ThreadPoolExecutor(2, 5, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
// ExecutorService pool = new ThreadPoolExecutor(2, 5, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
// ExecutorService pool = new ThreadPoolExecutor(2, 5, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy());
ExecutorService pool = new ThreadPoolExecutor(2, 5, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardOldestPolicy());
try {
for (int i = 1; i <= 9; i++) {
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
pool.shutdown();
}
}
}
# AbortPolicy()
pool-1-thread-1ok
pool-1-thread-2ok
pool-1-thread-2ok
pool-1-thread-1ok
pool-1-thread-3ok
pool-1-thread-4ok
pool-1-thread-2ok
pool-1-thread-5ok
java.util.concurrent.RejectedExecutionException: Task com.example.juc.TestRejectPolicy$$Lambda$1/1066516207@20ad9418 rejected from java.util.concurrent.ThreadPoolExecutor@31cefde0[Running, pool size = 5, active threads = 5, queued tasks = 3, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at com.example.juc.TestRejectPolicy.main(TestRejectPolicy.java:19)
# CallerRunsPolicy() 哪来的打发回哪,打回给main线程,由main线程执行
pool-1-thread-1ok
pool-1-thread-5ok
pool-1-thread-1ok
pool-1-thread-4ok
mainok
pool-1-thread-3ok
pool-1-thread-2ok
pool-1-thread-1ok
pool-1-thread-5ok
# DiscardPolicy()
pool-1-thread-2ok
pool-1-thread-5ok
pool-1-thread-4ok
pool-1-thread-3ok
pool-1-thread-1ok
pool-1-thread-5ok
pool-1-thread-4ok
pool-1-thread-2ok
# DiscardOldestPolicy()
pool-1-thread-1ok
pool-1-thread-3ok
pool-1-thread-4ok
pool-1-thread-5ok
pool-1-thread-2ok
pool-1-thread-4ok
pool-1-thread-3ok
pool-1-thread-1ok