线程池是一种多线程处理技术,它包含有多个线程的工作线程队列和一个线程池管理器。线程池的主要目的是避免频繁地创建和销毁线程,从而提高程序的性能和效率。
线程池的参数介绍
线程池的构造方法有很多我们在这值着重讲解其中的一个,也是参数最多的一个。
int corePoolSize, int maximumPoolSize,
这两个一个是核心线程数一个是最大线程数,在java标准库中线程池中的线程分为两部分一个是核心线程另一个就是非核心线程 ,核心线程+非核心线程的最大值就是最大线程数。
long keepAliveTime, TimeUnit unit
这两个参数第一个是时间的长度,第二个是时间的单位,时间的单位有很多种:
我们可以根据自己的需要进行选择合适的时间单位。
BlockingQueue<Runnable> workQueue
看到这个参数想必大家联想到了队列在线程池中也叫工作队列,也就是java中的“生产者消费者模型”, 就是一个阻塞队列,程序员使用的时候例如“submit”这样的方法,把要执行的任务设定到线程池里,线程池内部的工作线程负责执行这些任务。(Runnable接口本身的含义就是一段可以指向的任务),另外此处队列我们可以自行指定队列的容量和队列的类型。
ThreadFactory threadFactory
这个参数称为线程工厂,也是指“工厂设计模式”也是一种常见的设计模式。
工厂设计模式是一种在常见类实例时使用的一种设计模式,由于构造方法有坑,就比如坐标有两种表示形式一种是常规的(x,y)另一种是极坐标表示方法,如果我们使用相同的Double来表示参数那么就无法依靠重载来解决这个问题。
线程工厂就是Thread类的工厂类,通过这个类完成Thread的实例创建和初始话操作,此处的ThreadFactory就可批量的设置属性,此处的参数一般情况下不会进行调整,标准库给定了一个默认的值我们使用默认值即可:
RejectedExecutionHandler handler
这个参数是众多参数中最重要且最复杂的参数称为拒绝策略,我们来想象这样的一个情况,如果线程池的任务队列满了,还要继续个这个队列现价任务怎么办,在这里常量池不会进行阻塞而是通过另一种方式进行拒绝,java标准库给了四种不同的拒绝策略:
ThreadPoolExecutor.AbortPolicy,是一种直接拒绝的方式,简而言之就是如果任务队列满了直接报错,但是这种策略并不常用。
ThreadPoolExecutor.CallerRunsPolicy表示该线程拒绝指向,但不会停止,只不过是交给其他的线程执行。
ThreadPoolExecutor.DiscardPolicy表示把队列中最新的任务剔除,将最新的任务添加的原先最新任务的位置。
ThreadPoolExecutor.DiscardOlderestPolicy表示把队列中最老的任务剔除,将最新的任务添加的原先最老任务的位置。
任务队列满是无法避免的,因此我们只能结合实际情况选择合适的拒绝策略。
使用Executors 创建常见的线程池
常见线程池的方式有很多在这里我们只主要介绍两种常用的线程池:
第一种方式不可以自动进行扩容我们想要使用即可线程就有个线程,第二种线程池我们不需要将进行传入任何的参数,JVM会自动创建线程如何线程不够使用,也会自动进行扩容。
public class loop {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(4);
for (int i = 0; i < 100; i++) {
int id = i;
executorService.submit(()->{
Thread thread = Thread.currentThread();
System.out.println(id+""+thread);
});
}
Thread.sleep(3000);
executorService.shutdown();
}
}
在这里我们要使用shutdown()方法进行线程终止,这是因为我们在线程池中创建的线程都是前端线程,但是并没有办法结束线程的运行因此我们要使用shutdoun()方法使线程终止。