彻底搞懂线程池只需要知道线程池中:三大方法、7大参数,4中拒绝策略
池化技术
程序的运行,本质:占用系统的资源!优化资源的使用!==>池化技术
线程池,连接池,对象池
池化技术:事先准备好资源,有人要用,就来我这里拿,用完之后还给我
线程池的好处:
1.降低资源的消耗
2.提高响应速度
3.方便管理
线程复用、可以控制最大并发数、管理线程
三大方法
以下是阿里巴巴开发手册注意事项:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//Executors 简单理解为工具类 、三大方法
//使用了线程池之后,使用线程池来创建线程
public class Demo01 {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
//ExecutorService threadPool = Executors.newFixedThreadPool(5);//创建一个固定的线程池大小
//ExecutorService threadPool = Executors.newCachedThreadPool();//可伸缩的,遇强则强,遇弱则弱
try {
for (int i = 0; i < 10; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" OK");
});
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//线程池用完,程序结束,关闭线程池
threadPool.shutdown();
}
}
}
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;
}
模拟银行办理业务的场景:核心线程池大小–阻塞队列大小–最大线程池大小–拒绝策略
核心线程池大小数就是开的窗口数,假设一个常见,银行开始只开放了两个窗口,2个顾客已经占用,后面又来了3个客人,这3个客人就需要在候客区等待,这个候客区就是阻塞队列,如果阻塞队列容量大小为3,那说明这个时候候客区也满了,那么银行的其他窗口也要开放,又开放了3个窗口,一共就有5个窗口了,5就是最大线程池大小,如果又来了3个顾客,就占满了所有窗口,候客区也慢了,如果再来一个顾客,就会实施拒绝策略。
public class Demo02 {
public static void main(String[] args) {
//自定义线程池! 工作中使用ThreadPoolExecutor自定义线程池,不用Executors工具类的线程池,不安全,OOM
ExecutorService threadPool = new ThreadPoolExecutor(
2,//核心线程池大小
5,//最大线程池大小
3,//超时时间,超过后释放线程
TimeUnit.SECONDS,//超时单位
new LinkedBlockingQueue<>(3),//阻塞队列
Executors.defaultThreadFactory(),//线程工厂,一般是默认的
new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常!
try {
//最大承载:Queue + max
//超过了
for (int i = 1; i <= 10; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" OK");
});
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//线程池用完,程序结束,关闭线程池
threadPool.shutdown();
}
}
}
s
/**
* 拒绝策略
* 1.new ThreadPoolExecutor.AbortPolicy());//拒绝策略银行满了,还有人进来,不处理这个人,抛出异常
* 2.new ThreadPoolExecutor.CallerRunsPolicy());//哪来的去哪里!队列满了,新来的人(线程)交给main线程执行
* 3.new ThreadPoolExecutor.DiscardPolicy());//队列满了,丢掉任务,不会抛出异常
* 4. new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常!
*/
最大的线程如何设置!
了解:IO密集型,CPU密集型(调优)
知道了如何自定义线程池,那么该如何设置最大线程池大小呢?
//1.CPU 密集型 几核CPU就是几,可以保持CPU效率最高
//2.IO 密集型 >判断程序中十分耗IO的线程,如果程序 有15个大型任务 io十分占用资源。那么设置为2倍,30
ExecutorService threadPool = new ThreadPoolExecutor(
2,//核心线程池大小
Runtime.getRuntime().availableProcessors(),//最大线程池大小 根据CPU密集型来设置!!!!!
3,//超时时间,超过后释放线程
TimeUnit.SECONDS,//超时单位
new LinkedBlockingQueue<>(3),//阻塞队列
Executors.defaultThreadFactory(),//线程工厂,一般是默认的
new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常!
new LinkedBlockingQueue<>(3),//阻塞队列
Executors.defaultThreadFactory(),//线程工厂,一般是默认的
new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常!