线程和进程:
进程: 一个程序,是执行程序的一次执行过程。
一个进程往往包含若干个线程,线程是cpu调度和执行的单位。
Java默认有2个线程:main、GC
池化技术:
01:程序的运行,本质 :占用系统的资源! 优化资源的使用! =>池化技术
02:线程池、连接池、内存池、对象池///......创建、销毁。 十分浪费资源
03:池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。
线程池的好处:
01:降低资源的消耗
02:提高响应的速度
03:方便管理
(重点)线程复用、可以控制最大并发数、管理线程
线程池三大方法:
- Executors.newSingleThreadExecutor() 单个线程
- newFixedThreadPool(int nThreads) 创建一个固定的线程池的大小
运行结果:
最高同时有5个线程在执行!
- newCachedThreadPool() 大小可伸缩的缓冲池
package threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test01 {
public static void main(String[] args) {
// ExecutorService threadExecutor = Executors.newSingleThreadExecutor();//单线程
// ExecutorService threadExecutor1 = Executors.newFixedThreadPool(5);//创建一个固定大小的线程池
ExecutorService threadExecutor2 = Executors.newCachedThreadPool();//可以伸缩大小的线程池
try {
for (int i = 0; i < 10; i++) {
//使用了线程池之后,使用线程池来创建线程
threadExecutor2.execute(() -> {
System.out.println(Thread.currentThread().getName() + "执行!");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//为了确保关闭,放在finally里面
threadExecutor2.shutdown();//线程池用完,程序结束,关闭线程池
}
}
}
运行结果:
七大参数:
******7大参数原码分析******
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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
自定义线程池:
public class Test02 {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
try {
for (int i = 0; i < 9; i++) {
//使用了线程池之后,使用线程池来创建线程
threadPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName() + "执行!");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//为了确保关闭,放在finally里面
threadPoolExecutor.shutdown();//线程池用完,程序结束,关闭线程池
}
}
}
当人数超过阻塞队列加最大核心线程池大小时触发拒绝策略,会抛出异常。
四种拒绝策略:
图示理解拒绝策略:
举例,银行共有5个窗口(最大线程数),有常开的两个窗口处理业务(核心线程数);候客区(阻塞队列)有三个位置;当两个常开窗口(核心线程)以及候客区(阻塞队列)的位置都有人后,再来客户会开启另外三个窗口;当5个窗口(最大线程)和候客区(阻塞队列)都有人后,再来客户会启动拒绝策略。当窗口(线程)超过设定时间(超时时间)没有业务办理时(未调用)会关闭窗口(释放线程)。
new ThreadPoolExecutor.AbortPolicy()
(默认拒绝策略)银行满了,还有人进来,不处理这个人的,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy()
哪来的去哪里!
-
new ThreadPoolExecutor.DiscardPolicy()
队列满了,丢掉任务,不会抛出异常!
-
new ThreadPoolExecutor.DiscardOldestPolicy()
队列满了,尝试和最早的竞争,也不会抛出异常