线程的创建和关闭需要花费时间,可能会浪费资源,所以可以通过让线程复用来解决这个问题。
线程池就是这样一个概念,当需要创建线程的时候直接从线程池中获取,当关闭线程的时候直接归还线程给线程池。
ThreadPoolExecutor就是JDK提供的这样一个类。
它继承AbstructExecutorService类,AbstructExecutorService类实现ExecutorSerive接口,ExecutorSerive接口继承Executor接口。
具体方法可以在API中自行查看。
看一下ThreadPoolExtcutor的构造方法:
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;
}
下面是对它参数的解释:
corePoolSize:指定了线程池中线程的数量
maximumPoolSize:指定了线程池中线程的最大数量
keepAliveTime:当线程数量超过corePoolSize,多余线程的存活时间
TimeUnit:keepAliveTime的单位
workQueue:任务队列,被提交但还没执行的任务
threadFactory:用于创建线程
Handler:线程太多的拒绝策略
线程池有四个构造函数,其他三个只是把一些参数变成了默认而已,然后调用的这个构造函数。
对线程池类有点基本的了解之后接下来看看另一个类Extcutors。它是一个工厂类,可以从它获得特定功能的线程池。
public static ExecutorService newFixedThreadPool(xxxxxxx)
public static ExecutorService newSingleThreadExecutor(xxxx)
public static ExecutorService newCachedThreadPool(xxxxx)
public static ScheduledExecutorService newSingleThreadScheduledExecutor(xxxx)
public static ScheduledExecutorService newScheduledThreadPool(xxxxx)
功能分别是获得固定线程数目的线程池,获得一个线程的线程池,获得线程数量可变的线程池,获得可在给定时间执行的单线程池,获得可在给定时间执行的多线程池。
对于前三个来说,它们只是根据参数不同对ThreadPoolExecutor进行了封装。
而ScheduledExecutorService则是继承自ExecutorService,又在它的基础上添加了一些功能。
写个小例子:
public class demo implements Runnable{
public static void main(String[] args) {
ExecutorService es=Executors.newFixedThreadPool(2);
for(int i=0;i<10;i++)
{
es.submit(new Thread(new demo()));
}
}
public void run() {
System.out.println(System.currentTimeMillis());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
获得一个数量为2的固定线程数量线程池,在run里面每个线程sleep两秒,结果如下
可以清楚地看到每两秒后两个线程被执行。
线程的逻辑调度如下:
当线程池满,队列也满的时候,会采用拒绝策略,JDK提供了四种内置拒绝策略在线程池类里面:
具体的可以自行查找相关资料。
自此告一段落,线程池还有很多内容没有总结,后续再总结吧。