封装线程池工具类
最近发现当需要对某业务分拆多个模块同时执行,且不要求返回结果时,用到了线程池,可是线程池又没有地方关闭,消耗一定资源,因此封装一个线程池工具类,设定线程池大小,设定执行顺序,实例化一个对象,用该对象管理上述业务,用完即关闭。
代码如下:
package com.util.thread_tool;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.alibaba.fastjson.JSONObject;
/**
* Description: 多线程并行工具类
* @author: wyh
* @date 2020年8月7日
*/
public class ThreadTool {
/**
* 执行线程数
*/
private int size;
/**
* 当前完成执行线程数
*/
private int currentFinishSizeRecord;
/**
* 缓存线程池
*/
private ExecutorService pool = null;
/**
* 执行顺序 - FIFO:先进先出,顺序执行
*/
public final static String ORDER_TYPE_FIFO = "FIFO";
/**
* 执行顺序 - CACHE:缓存,有空闲则执行
*/
public final static String ORDER_TYPE_CACHE = "CACHE";
/**
* 执行顺序 - FIXED:缓存,固定数执行
*/
public final static String ORDER_TYPE_FIXED = "FIXED";
/**
* 构造器初始化["执行线程数","缓存线程池","当前完成执行线程数"]
* @param size
* @throws Exception
*/
public ThreadTool(int size, String orderType, Integer fixedNum) throws NullPointerException {
this.size = size;
switch(orderType) {
case ORDER_TYPE_FIFO :
this.pool = Executors.newSingleThreadExecutor();
break;
case ORDER_TYPE_CACHE :
this.pool = Executors.newCachedThreadPool();
break;
case ORDER_TYPE_FIXED :
if(fixedNum == null || fixedNum == 0) {
throw new NullPointerException("fixedNum is null.");
}else {
this.pool = Executors.newFixedThreadPool(fixedNum);
break;
}
default :
break;
}
this.currentFinishSizeRecord = 0;
}
/**
* 同步请求更改size
* @return
*/
private synchronized boolean setCurrentSizeRecord() {
if((this.currentFinishSizeRecord+1) <= this.size) {
this.currentFinishSizeRecord += 1;
return true;
}else {
if(!pool.isShutdown()) {
this.pool.shutdown();
}
System.out.println("线程池已满");
return false;
}
}
/**
* 执行的对象方法
* @param obj - 执行的对象实例
* @param methodName - 执行的方法名
* @param objs - 参数组,方法的传参,必须为对象
* @return
*/
public synchronized boolean execute(Object obj, String methodName, Object... objs) {
if(!setCurrentSizeRecord()) {
return false;
}
Thread thread = new Thread(()->this.threadExecute(obj, methodName, objs));
pool.submit(thread);
return false;
}
/**
* 获取当前完成的线程数
* @return
*/
public int currFinishSize() {
return this.currentFinishSizeRecord;
}
/**
* 中途关闭线程池,池内未加的线程将不增加,池内已有线程将继续执行到结束
*/
public void shutdown() {
this.size = 0;
if(!pool.isShutdown()) {
this.pool.shutdown();
}
}
/**
* 执行方法
* @param obj - 执行的对象实例
* @param methodName - 执行的方法
* @param objs - 参数组
* @return
*/
public boolean threadExecute(Object obj, String methodName, Object... objs) {
Class[] clzzs = new Class[objs.length];
for(int i = 0; i < objs.length; i++) {
clzzs[i] = objs[i].getClass();
}
try {
Method method = obj.getClass().getDeclaredMethod(methodName, clzzs);
Object value = method.invoke(obj, objs);
// 处理返回值
System.out.println("处理返回值,返回值内容 : " + JSONObject.toJSONString(value));
return true;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return false;
}
}
测试代码如下:
public class Test {
public static void main(String[] args) throws Exception {
ThreadTool threadTool = new ThreadTool(5, ThreadTool.ORDER_TYPE_CACHE, null);
for(int i = 0; i < 5; i++) {
final int n = i;
threadTool.execute(new Inner(), "say", "线程操作", n);
}
for(int i = 0; i < 5; i++) {
final int n = i;
threadTool.execute(new Inner2(), "add", n);
}
TimeUnit.SECONDS.sleep(2);
System.out.println("finishSize : " + threadTool.currFinishSize());
}
}
辅助测试代码如下:
Inner
public class Inner {
/**
* 描述内容
* @param content 内容
* @param count 第几个
* @return
*/
public boolean say(String content, Integer count) {
System.out.println("content : " + content + " , count : " + count);
return true;
}
}
Inner2
public class Inner2 {
private static int size;
public int add(Integer count) {
this.size += count;
System.out.println("累积 : " + size);
return size;
}
}