程序运行的本质:占用系统的资源==》优化资源的使用==池化技术:提前准备好资源,如果需要使用,则到池里用,用完后释放返回给池里以备下次或其他线程使用。
线程池、连接池、内存池、对象池、创建销毁都非常的浪费资源。
优点
新建单个线程池
/**
* @author
* @Date 2022/7/26
* @apiNote
*/
public class TApi {
public static void main(String[] args) {
ExecutorService singlePool=Executors.newSingleThreadExecutor();
try {
for (int i = 0; i < 100; i++) {
singlePool.execute(()->{//代替new Thread.start(),利用线程池执行线程
System.out.println(Thread.currentThread().getName()+"OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
singlePool.shutdown();//关闭线程池
}
}
}
新建固定个数的线程池
/**
* @author
* @Date 2022/7/26
* @apiNote
*/
public class TApi {
public static void main(String[] args) {
//新建5个线程池
ExecutorService fixedPool=Executors.newFixedThreadPool(5);
try {
for (int i = 0; i < 100; i++) {
fixedPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"====OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
fixedPool.shutdown();//关闭线程池
}
}
}
根据系统CPU大小,灵活创建线程池,CPU越好,创建线程池越多。
/**
* @author
* @Date 2022/7/26
* @apiNote
*/
public class TApi {
public static void main(String[] args) {
ExecutorService cachedPool=Executors.newCachedThreadPool();
try {
for (int i = 0; i < 100; i++) {
cachedPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"====OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
cachedPool.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
以下为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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
线程池不允许使用Executor去创建,而是通过ThreadPoolExecutor的方式,这样是为了让我们更好的了解线程池的运行规则,规避资源耗尽的风险。
Executor直接使用弊端为:
示例:
/**
* @author
* @Date 2022/7/26
* @apiNote
*/
public class TApi {
public static void main(String[] args) {
ExecutorService threadPool =new ThreadPoolExecutor(2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()//线程池满了,阻塞队列满了,进入后不再处理并抛出异常
);
try {
for (int i = 1; i <= 2; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"====OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
2.当有3个线程进行时
/**
* @author
* @Date 2022/7/26
* @apiNote
*/
public class TApi {
public static void main(String[] args) {
ExecutorService threadPool =new ThreadPoolExecutor(2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()//线程池满了,阻塞队列满了,进入后不再处理并抛出异常
);
try {
for (int i = 1; i <= 3; i++) {
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"====OK");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
4.五个线程:
5.六个线程:
两个核心线程池外加一个线程池在处理。
7.九个线程
当九个线程进行时,超过了设定最大线程池数量(5)+阻塞队列(3)个(8<9),触发拒绝策略abortPolicy,抛出异常。
除去上面的AbortPolicy拒绝策略,以下还有三种:
1.CallerRunPolicy拒绝策略
含义:哪来的回哪去
结果:
由主线程发出的,超过设定数量,会返回给主线程。
2.DiscardPolicy拒绝策略
结果:
达到设定线程池的数量8后,队列满后,之后第九个线程会被废弃掉,不抛出异常。
3.DiscardOldestPolicy
结果:
达到设定的最大线程数量8,第九个会尝试和第一个竞争,竞争成功会占用第一个,竞争失败就会自动丢弃掉。也不会抛出异常
最大线程如何定义