线程池原理
所谓线程池,通俗地理解就是有一个池子,里面存放着已经创建好的线程。当有任务提交给线程池时,池子中的某个线程会主动执行该任务。如果池子中的线程数量不足够应付数量众多的任务时,则需要自动扩充新的线程到池子;当任务比较少时,池子中的线程能够自动回收,释放资源。为了能够让异步地提交任务和缓存未处理的任务,需要有一个任务队列。
一个完整的线程池具备的要素:
- 任务队列:存放Runnable
- 线程数量管理功能:一个线程池必须能够很好地管理和控制线程数量,可通过三个参数实现,比如创建线程池时初始的线程数量为min;线程自动扩充时最大线程数量max,活跃数量active,三者之间关系min<active<max
- 任务拒绝策略:如果任务队列达到上限,则应有相应的拒绝策略来通知任务提交者
- 线程队列
自定义线程池
线程池初始化
自定义线程池MyThreadPool 继承Thread
/**
*
* @param min 线程池最小数量
* @param max 线程池最大数量
* @param active 线程池活跃数量
* @param task_queue_size 任务队列大小
* @param discardPolicy 拒绝策略
*/
public MyThreadPool(int min,int max,int active,int task_queue_size,DiscardPolicy discardPolicy) {
this.min=min;
this.active=active;
this.max=max;
this.task_queue_size=task_queue_size;
this.discardPolicy=discardPolicy;
init();
}
//默认初始化参数
//线程池默认最小数量
private final static int THREAD_MIN=4;
//线程池默认最大数量
private final static int THREAD_MAX=20;
//线程池默认活跃数量
private final static int THREAD_ACTIVE=10;
//成员变量
//线程池最小线程数量
private static int min;
//线程池最大数量
private static int max;
//线程池活跃数量
private static int active;
构造函数中的init()方法
/**
*
*/
private void init() {
//createWorkTask()方法下面再讲,这里就是创建min个线程
for (int i = 0;i<this.min; i++) {
createWorkTask();
}
//默认线程数量为min
this.size=min;
//启动线程池
this.start();
}
定义MyThreadPool内部枚举类
/**
* 枚举内部类
* @author Reyco
*枚举线程状态
*/
private enum TaskState{
FREE,RUNNING,BLOCKED,DEAD
}
定义拒绝策略
/**
* 拒绝异常
* @author Reyco
*
*/
public static class DiscardException extends Exception{
private static final long serialVersionUID = 1L;
public DiscardException(String message){
super(message);
}
}
/**
* 拒绝策略接口
* @author Reyco
*
*/
public interface DiscardPolicy{
public void discard() throws DiscardException;
}
//拒绝策略
private static DiscardPolicy discardPolicy;
//默认拒绝策略
private final static DiscardPolicy DEFAULT_DISCARDPOLICY=new DiscardPolicy() {
@Override
public void discard() throws DiscardException {
throw new DiscardException("Discard Exception");
}
};
定义工作线程
//创建线程队列
//采用LinkedList实现队列
private final static LinkedList<WorkerTask> THREAD_QUEUE=new LinkedList<>();
private static class WorkerTask extends Thread{
//默认线程状态为FREE
private volatile TaskState taskstate=TaskState.FREE;
public TaskState getTaskState() {
return this.taskstate;
}
public WorkerTask(ThreadGroup threadgroup,String name) {
super(threadgroup,name);
}
@Override
public void run() {
OUTER:
while(this.taskstate!=TaskState.DEAD) {
Runnable runnable;
synchronized (TASK_QUEUE) {
//如果任务队列为空,则阻塞
while(TASK_QUEUE.isEmpty()) {
try {
//任务队列为空,则wait
TASK_QUEUE.wait();
this.taskstate=TaskState.BLOCKED;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
break OUTER;//label标签
}
}
//按照队列的FIFO,执行任务队列的第一个任务
runnable=TASK_QUEUE.removeFirst();
}
//业务逻辑单元不应放在同步代码块中,影响执行效率
if(runnable!=null) {
this.taskstate=TaskState.RUNNING;
//执行任务
runnable.run();
this.taskstate=TaskState.FREE;
}
}
}
public void close() {
this.taskstate=TaskState.DEAD;
}
}
提交任务
//线程队列
private final static LinkedList<Runnable> TASK_QUEUE=new LinkedList<>();
//任务队列大小
private static int task_queue_size;
public void submitTask(Runnable runnable) {
//如果线程被destroy,则抛出异常
if(Mydestroy()) {
throw new RuntimeException("线程池已destroy");
}
synchronized (TASK_QUEUE) {
//如果任务队列这任务数量超出某个阈值,则抛出拒绝策略
if(TASK_QUEUE.size()>task_queue_size) {
try {
discardPolicy.discard();
} catch (DiscardException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//队列,放在最后
TASK_QUEUE.addLast(runnable);
//唤醒等待此监视器的线程
TASK_QUEUE.notifyAll();
}
}
关闭线程
public void shutDownTask() {
while(!TASK_QUEUE.isEmpty()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//获取当前线程队列数量
int initValue=THREAD_QUEUE.size();
if(initValue>0) {
for(WorkerTask task:THREAD_QUEUE) {
if(task.taskstate==TaskState.BLOCKED) {
task.close();
task.interrupt();
initValue--;
}else {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
this.destroy_flag=true;
System.out.println("The Thread_Pool is dead");
}
如何动态扩容线程池以及闲时回收
/**
* 线程池的run方法
*/
@Override
public void run() {
while(!Mydestroy()) {
System.out.println("Pool start"+TASK_QUEUE.size());
try {
Thread.sleep(100);
//如果任务队列大小大于活跃线程数量且当前线程数量小于活跃线程数量
//则扩容至活跃线程数量大小
if(TASK_QUEUE.size()>active && size<active) {
System.out.println("扩容线程前:"+THREAD_QUEUE.size());
for(int i=size;i<active;i++) {
createWorkTask();
}
System.out.println("扩容线程成功:"+THREAD_QUEUE.size());
size=active;
}
//如果任务队列大小大于最大线程数量且当前线程数量小于最大线程数量
//则扩容至最大线程数量大小
else if(TASK_QUEUE.size()>max && size<max) {
System.out.println("扩容线程前:"+THREAD_QUEUE.size());
for(int i=size;i<max;i++) {
createWorkTask();
}
System.out.println("扩容线程成功:"+THREAD_QUEUE.size());
size=max;
}
//任务队列为空且线程数量大于active
//则回收线程数量至active个
else if(TASK_QUEUE.isEmpty() && size>active) {
synchronized (TASK_QUEUE) {
int releaseSize=size-active;
for(Iterator<WorkerTask> it=THREAD_QUEUE.iterator();it.hasNext();) {
if(releaseSize<=0) {
break;
}else {
WorkerTask task=it.next();
task.close();
task.interrupt();
it.remove();
releaseSize--;
}
}
}
size=active;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
测试类
public static void main(String[] args) {
MyThreadPool myThreadPool = new MyThreadPool();
for(int i=0;i<40;i++) {
myThreadPool.submitTask(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
myThreadPool.shutDownTask();
}
经测试,该线程池可以较好地工作并实现自动扩容线程池大小和闲时回收功能。
jar 包下载传送门