文章插图
线程池化技术,是通过一个公用的线程队列,将一个或多个线程进行统一资源调用,可以支持线程资源的重复使用的技术,可以有效的避免因为线程调用创建和销毁线程过程带来的资源消耗问题 。
为什么要使用线程池?
1、可以通过重复利用创建好的线程来降低线程创建和销毁造成的资源消耗
2、可以提升系统响应速度,因为核心线程是一直存在的,所以多线程任务不需要等待线程创建就可以立即执行任务 。
3、可以利用线程池对线程资源进行统一的管理,避免线程创建过多导致的内存溢出问题等问题 。
JAVA中如何来实现线程池的管理的?
Java是从JDK1.5开始的时候,将工作单元与线程执行机制进行了分离来提供线程池的使用管理机制,其中工作单元主要就是包括Runnable和Callable,而线程的执行机制则是交给了executors来提供,代码如下 。
首先我们来创建一个用于测试的线程类 。
【Java中如何去创建一个线程池?】
public class TestThread implements Runnable {private String count;public TestThread(String count) {this.count = count;@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+" 开始计数 Count = "+count);executeCount();System.out.println(Thread.currentThread().getName()+" 结束计数");private void executeCount() {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();@Overridepublic String toString(){return this.count;
创建测试主类
public class SimpleTheadPool {public static void main(String[] args) {// 创建线程池ExecutorService executorService = Executors.newFixedThreadPool(5);//创建执行线程操作for (int i = 0; i < 10; i++) {Runnable testThread = new TestThread(String.valueOf(i));executorService.execute(testThread);executorService.shutdown();while (executorService.isTerminated()){System.out.println("完成所有线程");
在测试类中,创建了一个固定大小的线程池,并且给线程池分配了10个需要执行的测试任务,因为线程池的初始大小是5,所以无法一次容纳10个线程的处理,所以当线程进入之后,会有一部分线程进入到等待状态,当前面进入的线程执行完成之后,后续的线程就会自动进入执行,执行效果如下图所示 。
文章插图
从执行结果来看,线程池中只存在了五个线程,并且这五个线程并不会随着工作执行完成而销毁,会一直等待分配线程执行任务,一直到线程池调用了销毁函数来进行销毁 。
Executors使用了ExecutorService提供的线程实现,并且newFixedThreadPool() 方法创建了如下的一个线程池类 。
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue());
下面我们就来看看ThreadPoolExecutor线程池类
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {// 省略代码
corePoolSize:核心线程数,当我们往线程池中添加一个任务之后,线程池会创建一个新的线程去执行任务,当创建的线程数等于corePoolSize之后 。继续提交任务就会被阻塞到队列中,等待执行 。当然如果调用了prestartAllCoreThreads()方法,线程池也会启动所有的核心线程 。
workQueue:用来保存等待执行任务的阻塞队列 。
maximumPoolSize:线程池中被允许的最大线程数 。当等待执行阻塞队列装满之后,如果继续提交任务,则会继续创建线程去执行任务,前提是创建的线程数要小于maximumPoolSize值 。这里需要注意的是如果队列可以存放的任务是无限的,那么这个参数就不会起作用,因为队列会一直存放等待线程 。
keepAliveTime:线程空闲等待时间,当线程没有需要执行的任务的时候,就会在等待指定时间之后被销毁,默认情况下只会销毁超过corePoolSize数的线程 。
unit:设置等待的线程时间单位
threadFactory:创建线程的工厂类 。通过自定义的方式可以给每个线程创建一个具有识别性的线程名称,用于后续问题定位 。
handler:线程拒绝策略,当队列满的时候,如果没有空闲线程执行任务,那么就需要拒绝策略的参与 。
推荐阅读
- Golang中如何判断两个Slice是否相等?
- Java 注解基础知识,掌握的人不足10%
- |多地中小学教师与编制脱钩,副作用逐渐显现,师范生该何去何从
- Java文件的读写操作方法
- APP开发用什么语言好?Java和PHP的区别在哪?
- SpringBoot中如何实现限流,这种方式才叫优雅!
- 值得考虑的七个出色的JavaScript项目
- 掌握Fork/Join 框架,证明你Java毕业了
- 深入了解 JavaScript 内存泄漏
- JavaScript中根据字符串中的范围规则,判断当前值是否符合条件