一、什么是线程池(What)?
- 首先,咱们要了解什么是多线程。一条线程指的是过程中一个繁多程序的控制流,一个过程中能够并发多个线程,每条线程并行执行不同的工作。
<多线程> 翻译成人话:相似大家进超市门,很多人挤一个入口通道,太慢了。那就多开明几个入口通道,短时间内解决更多人流量。
- 而后,再来了解什么是线程池。能够了解成,当时创立好一堆线程,供多任务来应用这些线程,用完后偿还到池内,在设置的某时间段内不销毁,以备其余工作应用。
二、为什么要应用线程池(Why)?
咱们应用线程的时候就去创立一个线程,这样实现起来十分简便,然而就会有一个问题:
如果并发的线程数量很多,并且每个线程都是执行一个工夫很短的工作就完结了,这样频繁创立线程就会大大降低零碎的效率,因为频繁创立线程和销毁线程须要工夫的。
那么有没有一种方法使得线程能够复用,就是执行完一个工作,并不被销毁,而是能够继续执行其余的工作?这就是线程池的诞生起因。
三、怎么应用线程池(How)?
多线程的应用很重要,java内置包里必定就有解决方案。
线程池执行器:
java.util.concurrent.ThreadPoolExecutor
这里咱们对这个执行器进行简略的设置,写成工具类,便于多处调用。代码如下:
1. 线程池执行器-工具类
import java.util.concurrent.*;/** * @author dayaocool * @version 1.0 * @date 2020/08/12 14:27 */public class ThreadPoolUtil { // 定义一些配置常量,也能够读取内部配置文件 // 初始化开启的线程数,(可更改查看不同) private static final int corePoolSize = 2; // 最大线程数量,不能比 开启的线程数(corePoolSize)小。 private static final int maximumPoolSize = 8; // 工作队列容量,不能比 最大线程数量(maximumPoolSize)小, // 否则 会触发 队满回绝策略(MyRejectHandler) private static final BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(8); // 线程存活工夫 (超过该工夫无任何应用才回销毁线程) private static final long keepAliveTime = 2; // 线程存活工夫的单位,秒 private static final TimeUnit unit = TimeUnit.SECONDS; // 线程池工厂的 实现类 private static final ThreadFactory threadFactory = new MyThreadPoolFactory(); // 工作队列满载回绝处理程序 实现类 private static final RejectedExecutionHandler rejectedExecutionHandler = new MyRejectHandler(); /** * 线程池工厂的 实现类 (外部类) */ private static class MyThreadPoolFactory implements ThreadFactory { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r, "新线程-"); System.out.println(thread.getName() + "创立实现"); return thread; } } /** * 工作队列满载回绝处理程序 实现类 (外部类) */ private static class MyRejectHandler implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // ...回绝解决的代码可扩大... System.out.println(r.toString() + " 已被回绝"); } } /** * 获取 线程池执行器 * @return 线程池执行器 */ public static ThreadPoolExecutor getExecutor() { return new ThreadPoolExecutor( corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, rejectedExecutionHandler ); }}
2. 模仿线程工作类
/** * @author dayaocool * @version 1.0 * @date 2020/8/12 14:33 */public class MyTask implements Runnable { private String name; public MyTask(String name) { this.name = name; } @Override public void run() { try { // 模拟程序3秒耗时 Thread.sleep(3000); System.out.println(this.toString() + " 运行完结了!"); } catch (Exception e) { e.printStackTrace(); } } @Override public String toString() { return "大尧啊,您的 MyTask{" + "name='" + name + '\'' + '}'; }}
3. 运行调用
/** * @author dayaocool * @version 1.0 * @date 2020/8/12 14:48 */public class RunTest { public static void main(String[] args) { // 模仿 5个 工作 MyTask myTask1 = new MyTask("工作1"); MyTask myTask2 = new MyTask("工作2"); MyTask myTask3 = new MyTask("工作3"); MyTask myTask4 = new MyTask("工作4"); MyTask myTask5 = new MyTask("工作5"); // 从线程池工具类 获取到 线程执行器 ThreadPoolExecutor executor = ThreadPoolUtil.getExecutor(); // 并发多线程 执行工作 executor.execute(myTask1); executor.execute(myTask2); executor.execute(myTask3); executor.execute(myTask4); executor.execute(myTask5); }}
输入
- 先输入 初始化开启的线程数,corePoolSize=2,即开了2个线程
新线程-创立实现
新线程-创立实现
- 持续输入 (工作先后问题这是cpu资源抢占机会的问题)
大尧啊,您的 MyTask{name='工作2'} 运行完结了!
大尧啊,您的 MyTask{name='工作1'} 运行完结了!
- 持续输入
大尧啊,您的 MyTask{name='工作3'} 运行完结了!
大尧啊,您的 MyTask{name='工作4'} 运行完结了!
- 最初输入
大尧啊,您的 MyTask{name='工作5'} 运行完结了!
5个工作,分2个并发,执行实现。
总结
线程池主动治理多线程的资源开销,让多线程编程更高效,解决多任务并行迟缓的问题。spring boot 2框架对线程池的应用更简略,举荐。