一 概述
对于一个系统来说,线程和数据库连接这些资源是非常重要的,而且它们相关线程的创建和销毁对应到的是操作系统的线程,所以反复执行相关操作是非常消耗系统资源的。当我们每次需要的时候就创建,不需要的时候就销毁的操作是非常让费资源的。所以我们可以借助缓存策略,也就是使用线程池。
二 Java使用线程池的好处
对于Java线程而言,每个线程都会对应到操作系统中的线程操作,所以当我们反复创建和销毁线程的时候会给操作系统带来极大的消耗,如创建时的内存消耗和销毁时的GC压力。使用了线程池之后我们就可以通过创建少量的线程来保证系统功能能够正常运行的同时也不会消耗系统太大的性能,如内存和CPU资源消耗。同时,减少了线程的创建和销毁操作所耗费的时间,实现对线程的统一管理。
三 线程池的使用
当服务器收到大量的请求时是非常适用线程池的,它可以大大的减少线程的创建和销毁的次数,提高服务器的工作效率。
注:不仅仅是java中存在线程池,Tomcat中也存在线程池的概念。
import java.util.concurrent.ThreadPoolExecutor; //java中的线程池
import org.apache.tomcat.util.threads.ThreadPoolExecutor; //Tomcat中的线程池
阅读源码可以发现一个很神奇的事情,就是Tomcat中的线程池类于java中的线程池类是继承关系
package org.apache.tomcat.util.threads;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutor extends java.util.concurrent.ThreadPoolExecutor {
//其中一个构造函数
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
this.prestartAllCoreThreads();
}
}
四 线程池构造函数的参数
参数名 | 参数类型 | 参数的含义 |
corePoolSize | int | 核心线程数 |
maxinumPoolSize | int | 最大线程数 |
keepAliveTime | long | 空闲线程存活的时间 |
unit | | 时间单位 |
workQueue | | 任务存储队列 |
threadFactory | | 当前线程池需要新的线程的时候,会使用threadFactory生成新的线程 |
handler | | 由于线程池无法接受你所提交任务的拒绝策略 |
五 线程池参数的解读
- corePoolSize:是指线程池中核心线程的数量,线程池在完成初始化之后,默认情况下,线程池中并没有任何线程,线程池会等到接收到任务的时候再创建相应的线程进行任务处理。这种情况下,如果设置corePoolSize=6,当有小于获得等于6个任务请求时,就会使用这6个线程来处理。之后这6个线程在线程池正常工作的情况下一直存活。
- maxinumPoolSize:线程池中的线程除了核心程之外,线程池也会在此基础上增加一些新的线程,但是增加新的线程的数量有一个上限,即最大量为maxinumPoolSize。由于系统每天需要的线程数不一样,可能多可能少,所以线程池线程最大值maxinumPoolSize的存在很好的为线程池提供了灵活扩展能力。
- keepAliveTIme:如果线程池当前的线程数多余核心线程数,当这些多余的线程空闲时间超过keepAliveTime的时候,它们就会别终止,并会被线程会被GC回收。(核心线程默认是不会被回收的,除非设置参数allowCoreThreadTimeOut = true)。
- unit:指定线程中时间单位。
- workQueue:workQueue为工作存储队列,当任务线程数超过线程池中执行线程的数量的时候,多余的任务线程就会被放入存储队列中,这些任务线程会等到核心线程执行的任务完成之后才会被执行线程获取执行。此外,该工作队列是可以设置有容量的,多余的线程又超过了工作队列的容量的时候,线程池就会进行相应的扩容,即增加一些执行线程来执行线程任务,但是扩容的量是不会超过最大线程连接数manxinumPoolSize。
- ThreadFactory:新的线程是由ThreadFactory创建的,默认使用Executors.defaultThreadFactory(),创建出来的线程都是在同一个线程组中的,并且拥有同样的NORM_PRIORITY优先级并且都不是守护线程。如果使用我们自己指定的线程工厂ThreadFactory就可以改变线程名,线程组,优先级,是否为守护线程(实际情况下默认线程工程就能满足需求)。
- handler:是接口RejectedExecutionHandler型的变量,为线程池无法接受的提交任务提供拒绝策略。