最近温习了Java线程池相关的知识,感觉太久没看,都忘了,特此记录。
1. Excutor: java线程池的顶层接口,提供了execute(Runnable r)方法。
2. ExcutorService: 继承自execute方法的一个接口,是为Executor服务的,用于进行线程的提交(submit),执行(invokeAll,invokeAny)等操作。
3. AbstracExecutorService: 实现了ExecutorService的一个虚函数,主要是对ExecutorService的方法提供默认实现。
4. ThreadPoolExcutor: 线程池,继承自AbstractExecutorSerice虚函数,主要方法有: 线程池创建,线程池corePoolSiez,maximumPoolSize等参数的设置,线程池状态变化等。
5. ScheduledExecutorService: 继承自ExecutorService接口,提供了延迟和周期性执行的ExecutorService。
6. ScheduledThreadPool: 实现了ScheduledExecutorService接口,相当于一个提供延迟和周期执行的线程池。
7. Executors: 是一个静态工厂类,通过静态工厂方法返回ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 等类的对象。
上面是Java线程池的基本的架构:下面我们通过例子来学习Java线程池相关知识点。
1. 创建一个Java线程池,首先查看Java线程池的构造函数:
/** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters. * * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param maximumPoolSize the maximum number of threads to allow in the * pool * @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating. * @param unit the time unit for the {@code keepAliveTime} argument * @param workQueue the queue to use for holding tasks before they are * executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method. * @param threadFactory the factory to use when the executor * creates a new thread * @param handler the handler to use when execution is blocked * because the thread bounds and queue capacities are reached * @throws IllegalArgumentException if one of the following holds:<br> * {@code corePoolSize < 0}<br> * {@code keepAliveTime < 0}<br> * {@code maximumPoolSize <= 0}<br> * {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} * or {@code threadFactory} or {@code handler} is null */ 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,workQueue,keepAliveTime,threadFactory,handler;
下面通过例子来学习:
1. 当创建的线程超过了线程池能提供的服务数量之后:并且采用默认的拒绝策略: AbortPolicy此时会产生什么情况呢?
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class Test{ public static void main(String[] args0) throws InterruptedException{ /** * corePoolSize: 核心池的大小。就是现在线程池包含的线程的数量 * maximumPoolSize: 最大线程池线程数量: 就是这个线程池最多能包含多少个线程 * KeepAliveTime: 通常与allowCoreThreadTimeout连用 其中allowCoreThreadTimeout: 是否允许线程在空闲时存活 默认false * keepAliveTime: 指的是当allowCoreThreadTimeout为true的时候,能够忍受线程空闲的时间 * unit: 空闲时间的单位 * workQueue:是一个BlockingQueue类型,是一个阻塞队列,当当前线程超过它的容量的时候就是进入到workQueue * threadFactory: 线程创建工厂 * handler: 线程拒绝策略句柄 */ ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 5, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3)); //上面我们创建了一个线程池,并且线程中的ThreadFactory采用的是默认的工厂方式 为了后面方面我们暂时使用了ThreadPoolExecutor的默认拒绝策略 AbortPolicy //创建了一个阻塞队列,队列大小为5 for(int i=0;i<10;i++){ ThreadTest test = new ThreadTest(i+""); threadPoolExecutor.execute(test); Thread.sleep(100); //System.out.println(threadPoolExecutor.getPoolSize()); } threadPoolExecutor.shutdown(); System.out.println(threadPoolExecutor.isShutdown()); } } class ThreadTest implements Runnable{ String name = ""; public ThreadTest(String temp){ this.name = temp; } public void run() { System.out.println(name+"线程正在开始执行"); try { ///模拟线程正在执行任务 Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(name+"线程执行完成"); } }我们创建了十个线程,但是线程池的maximumPoolSize和BlockingQueue之和为8,采用abortPiolicy策略,那么一定会抛出异常。可以从结果中看出,当线程 0线程正在开始执行 1线程正在开始执行 5线程正在开始执行 6线程正在开始执行 7线程正在开始执行 Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task ThreadTest@55f96302 rejected from java.util.concurrent.ThreadPoolExecutor@3d4eac69[Running, pool size = 5, active threads = 5, queued tasks = 3, completed tasks = 0] <span style="white-space:pre"> </span>at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(Unknown Source) <span style="white-space:pre"> </span>at java.util.concurrent.ThreadPoolExecutor.reject(Unknown Source) <span style="white-space:pre"> </span>at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source) <span style="white-space:pre"> </span>at Test.main(Test.java:23) 0线程执行完成 2线程正在开始执行 1线程执行完成 3线程正在开始执行 5线程执行完成 4线程正在开始执行 6线程执行完成 7线程执行完成 2线程执行完成 3线程执行完成 4线程执行完成 自己画了一个图,来表示这个过程,但是线程执行时间不同,进程图调用过程图就不同了。从图和上面的日志可看出: 执行到异常的时候就不再执行了。而是继续完成pool和Queue里面的线程。
后续策略待续