最近温习了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里面的线程。
后续策略待续