线程池
以下整理自 http://www.cnblogs.com/dolphin0520/p/3932921.html (万分感谢)
1.ThreadPoolExecutor类
ava.uitl.concurrent.ThreadPoolExecutor类是线程池中最核心的一个类
,因此如果要透彻地了解Java中的线程池,必须先了解这个类。
下面我们来看一下ThreadPoolExecutor类的构造器。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
...
}
几个构造器都有如下参数
-
corePoolSize:核心池的大小,这个参数跟后面讲述的线程池的实现原理有非常大的关系。
在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行
任务,除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,从这2个方法的
名字就可以看出,是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或者一
个线程。默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个
线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; -
maximumPoolSize:线程池最大线程数,这个参数也是一个非常重要的参数,它表示在线程池中最
多能创建多少个线程; -
keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中
的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于
corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到
keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了
allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,
keepAliveTime参数也会起作用,直到线程池中的线程数为0; -
workQueue:一个阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响,一般来说,这里的阻塞队列有以下几种选择:
-
ArrayBlockingQueue;
-
LinkedBlockingQueue;
-
SynchronousQueue;
ArrayBlockingQueue和PriorityBlockingQueue使用较少,一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。
- 对于corePool,ThreadPoll,BlockingQueue的关系,如下图
- unit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:
TimeUnit.DAYS; //天
TimeUnit.HOURS; //小时
TimeUnit.MINUTES; //分钟
TimeUnit.SECONDS; //秒
TimeUnit.MILLISECONDS; //毫秒
TimeUnit.MICROSECONDS; //微妙
TimeUnit.NANOSECONDS; //纳秒
- threadFactory:线程工厂,主要用来创建线程;
- handler:表示当拒绝处理任务时的策略,有以下四种取值:
- ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
- ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
- ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
2.继承关系
- AbstractExecutorService
public abstract class AbstractExecutorService implements ExecutorService {
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { };
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { };
public Future<?> submit(Runnable task) {};
public <T> Future<T> submit(Runnable task, T result) { };
public <T> Future<T> submit(Callable<T> task) { };
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
boolean timed, long nanos)
throws InterruptedException, ExecutionException, TimeoutException {
};
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
};
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
};
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
};
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
};
}
ExecutorService接口:
public interface ExecutorService extends Executor {
void shutdown();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
Excutior接口
public interface Executor {
void execute(Runnable command);
}
-
Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;
-
然后ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;
-
抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;
-
然后ThreadPoolExecutor继承了类AbstractExecutorService。
3.在ThreadPoolExecutor类中有几个非常重要的方法
execute()
submit()
shutdown()
shutdownNow()
-
execute()方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,
这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,
交由线程池去执行。 -
submit()方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了
具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任
务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,
会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果 -
shutdown()和shutdownNow()是用来关闭线程池的
4、使用示例(以下代码根据原博主改编了一下,能动态获取线程池的数据)
package xyh;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author XiangYida
* @version 2019/3/4 19:36
*/
public class Test {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 15, 200, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(12));
System.out.println(" 核心池的数量" + executor.getCorePoolSize() + " 线程池中线程数目:" + executor.getPoolSize() + ",队列中等待执行的任务数目:" +
executor.getQueue().size() + ",已执行完别的任务数目:" + executor.getCompletedTaskCount());
for (int i = 0; i < 15; i++) {
MyTask myTask = new MyTask(i);
executor.execute(myTask);
}
Get g = new Get(executor);
new Thread(g).start();
executor.shutdown();
}
}
class MyTask implements Runnable {
private int taskNum;
public MyTask(int num) {
this.taskNum = num;
}
@Override
public void run() {
System.out.println("正在执行task " + taskNum);
try {
Thread.currentThread().sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task " + taskNum + "执行完毕");
}
}
class Get implements Runnable {
ThreadPoolExecutor executor;
public Get(ThreadPoolExecutor executor) {
this.executor = executor;
}
@Override
public void run() {
while (executor.getPoolSize() != 0) {
System.out.println(" 核心池的数量" + executor.getCorePoolSize() + " 线程池中线程数目:" + executor.getPoolSize() + ",队列中等待执行的任务数目:" +
executor.getQueue().size() + ",已执行玩别的任务数目:" + executor.getCompletedTaskCount());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(" 核心池的数量" + executor.getCorePoolSize() + " 线程池中线程数目:" + executor.getPoolSize() + ",队列中等待执行的任务数目:" +
executor.getQueue().size() + ",已执行完别的任务数目:" + executor.getCompletedTaskCount());
}
}
实验结果
---------------------------核心池的数量3 线程池中线程数目:0,队列中等待执行的任务数目:0,已执行完别的任务数目:0
正在执行task 0
正在执行task 1
正在执行task 2
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:12,已执行玩别的任务数目:0
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:12,已执行玩别的任务数目:0
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:12,已执行玩别的任务数目:0
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:12,已执行玩别的任务数目:0
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:12,已执行玩别的任务数目:0
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:12,已执行玩别的任务数目:0
task 0执行完毕
正在执行task 3
task 1执行完毕
task 2执行完毕
正在执行task 4
正在执行task 5
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:9,已执行玩别的任务数目:3
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:9,已执行玩别的任务数目:3
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:9,已执行玩别的任务数目:3
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:9,已执行玩别的任务数目:3
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:9,已执行玩别的任务数目:3
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:9,已执行玩别的任务数目:3
task 3执行完毕
正在执行task 6
task 4执行完毕
task 5执行完毕
正在执行task 7
正在执行task 8
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:6,已执行玩别的任务数目:6
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:6,已执行玩别的任务数目:6
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:6,已执行玩别的任务数目:6
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:6,已执行玩别的任务数目:6
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:6,已执行玩别的任务数目:6
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:6,已执行玩别的任务数目:6
task 6执行完毕
正在执行task 9
task 7执行完毕
task 8执行完毕
正在执行task 10
正在执行task 11
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:3,已执行玩别的任务数目:9
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:3,已执行玩别的任务数目:9
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:3,已执行玩别的任务数目:9
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:3,已执行玩别的任务数目:9
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:3,已执行玩别的任务数目:9
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:3,已执行玩别的任务数目:9
task 9执行完毕
正在执行task 12
task 10执行完毕
task 11执行完毕
正在执行task 13
正在执行task 14
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:0,已执行玩别的任务数目:12
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:0,已执行玩别的任务数目:12
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:0,已执行玩别的任务数目:12
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:0,已执行玩别的任务数目:12
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:0,已执行玩别的任务数目:12
---------------------------核心池的数量3 线程池中线程数目:3,队列中等待执行的任务数目:0,已执行玩别的任务数目:12
task 12执行完毕
task 14执行完毕
task 13执行完毕
---------------------------核心池的数量3 线程池中线程数目:0,队列中等待执行的任务数目:0,已执行完别的任务数目:15