1、创建线程池
package com.bee.vip.sys.util;
import com.alibaba.fastjson.JSON;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Created by QingLong on 2018/8/2.
*/
public class CustomThreadPool {
private static final Logger logger = Logger.getLogger(CustomThreadPool.class);
private final static int DEFAULT_MAX_THEARD = 1;// 默认最大线程池个数
private final static int DEFAULT_MAX_EXECUTESIZE = 1;// 默认单个线程最大执行数据的个数
private ExecutorService executorService;
public CustomThreadPool(int maxTheard) {
logger.info(String.format("定义线程池最大个数:%s", maxTheard));
if (maxTheard == 0) {
maxTheard = DEFAULT_MAX_THEARD;
logger.info(String.format("因为定义线程池最大个数:0 所以采用默认:" + DEFAULT_MAX_THEARD));
}
executorService = Executors.newFixedThreadPool(maxTheard);
}
/**
*
* @param inputs 需要处理的任务集合
* @param maxExecuteSize 单个线程执行的任务的数量
* @param cls 反射执行的类
* @param methodName 反射执行的方法名称
* @param objects 其他参数集合
* @return
*/
public List<Future<ThreadResultVO>> executeObject(List inputs, int maxExecuteSize, Class cls, String methodName, Object... objects) {
long startTime = System.currentTimeMillis();
logger.info(String.format("任务单号:%s 最大执行个数:%s 入参数据:%s", startTime, maxExecuteSize, JSON.toJSONString(inputs)));
logger.info(String.format("调用类:%s 调用方法:%s 额外传参:%s", cls.getName(), methodName, JSON.toJSONString(objects)));
if (maxExecuteSize == 0) {
maxExecuteSize = DEFAULT_MAX_EXECUTESIZE;
logger.info(String.format("因为定义单个线程最大执行个数:0 所以采用默认:" + DEFAULT_MAX_EXECUTESIZE));
}
if (inputs == null || inputs.isEmpty()) {
return Collections.EMPTY_LIST;
}
int times = (inputs.size() + maxExecuteSize - 1) / maxExecuteSize;
CountDownLatch countDownLatch = new CountDownLatch(times);
List<Future<ThreadResultVO>> futures = new ArrayList<Future<ThreadResultVO>>(0);
try {
for (int threadSize = 0; threadSize < times; threadSize++) {
if (threadSize == times - 1) {
Future<ThreadResultVO> submit = executorService.submit(new InvokeOtherClassMethodCallable(
inputs.subList(threadSize * maxExecuteSize, inputs.size()), countDownLatch, cls, methodName, objects));
futures.add(submit);
} else {
Future<ThreadResultVO> submit = executorService.submit(new InvokeOtherClassMethodCallable(
inputs.subList(threadSize * maxExecuteSize, (threadSize + 1) * maxExecuteSize), countDownLatch, cls, methodName, objects));
futures.add(submit);
}
}
// 等待子线程的结束
countDownLatch.await();
} catch (Exception e) {
logger.error(String.format("任务单号:%s 执行异常:", startTime));
e.printStackTrace();
} finally {
logger.info(String.format("任务单号:%s 已经完成。耗时:%s 毫秒", startTime, System.currentTimeMillis() - startTime));
executorService.shutdown();
return futures;
}
}
}
2、执行线程的方法,具体方法为反射调用
package com.bee.vip.sys.util;
import com.alibaba.fastjson.JSON;
import org.apache.log4j.Logger;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
/**
* Created by QingLong on 2018/8/2.
*/
public class InvokeOtherClassMethodCallable implements Callable<ThreadResultVO> {
private static final Logger log = Logger.getLogger(InvokeOtherClassMethodCallable.class);
private CountDownLatch countDownLatch;
private Class callbackClass;
private String methodName;
private Object[] objects;
public InvokeOtherClassMethodCallable(List executeParams, CountDownLatch countDownLatch, Class callbackClass, String methodName, Object... objects) {
this.countDownLatch = countDownLatch;
this.callbackClass = callbackClass;
this.methodName = methodName;
this.objects = new Object[objects.length + 1];
int i = 0;
this.objects[i++] = executeParams;
for (Object object : objects) {
this.objects[i++] = object;
}
}
public ThreadResultVO call() {
ThreadResultVO threadResultVO = new ThreadResultVO();
try {
// 模拟业务执行,可反射调用其他类方法
Method tempMethod = null;
log.info(Thread.currentThread() + "执行开始。。。。");
for (Method method : callbackClass.getMethods()) {
// 以方法名查找方法
if (methodName.equals(method.getName())) {
// 以参数个数及类型定位
Class[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != objects.length) {
continue;
}
int parameterIndex = 0;
for (Object object : objects) {
if (object.getClass().isInstance(parameterTypes[parameterIndex++])) {
continue;
}
// 最后一次获取方法
if (parameterIndex == parameterTypes.length) {
tempMethod = method;
}
}
}
if (tempMethod != null) {
break;
}
}
if (tempMethod == null) {
throw new RuntimeException(String.format("没有找到反射的方法:%s 参数类型:%s", methodName, JSON.toJSONString(objects)));
}
Object tempResult = tempMethod.invoke(callbackClass.newInstance(), objects);
threadResultVO.setSuccess(true);
threadResultVO.setResult(tempResult);
} catch (Exception e) {
threadResultVO.setSuccess(false);
threadResultVO.setException(String.format("异常类型:%s 异常内容:%s", e.getCause().getClass().getName(), e.getCause().getMessage()));
log.error("异步执行失败:");
e.printStackTrace();
} finally {
log.info(Thread.currentThread() + "执行结束。。。。");
// 计数减一
countDownLatch.countDown();
return threadResultVO;
}
}
}
3、具体执行的任务
package com.bee.vip.sys.util;
import com.bee.fd.service.IntentionVipService;
import com.bee.framework.i.bp.core.CoreException;
import com.bee.utils.common.Constants;
import java.util.ArrayList;
import java.util.List;
/**
* Created by QingLong on 2018/8/2.
*/
public class TaskManager {
public static List<ArrayList<String>> dealTask(List<ArrayList<String>> dataList, String userId, String batchNum, IntentionVipService intentionVipService) {
Long startTime = System.currentTimeMillis();
List<ArrayList<String>> errList = new ArrayList<>(0);
try {
errList = intentionVipService.uploadIntentionFile(dataList, Constants.VIP_HIGHTSEA_STATUS, userId, batchNum);
} catch (CoreException e) {
e.printStackTrace();
}
System.err.println("当前线程是:"+Thread.currentThread().getName() +"-共耗时:"+ (System.currentTimeMillis()-startTime));
return errList;
}
}
4、返回的实体类
package com.bee.vip.sys.util;
/**
* Created by QingLong on 2018/8/2.
*/
public class ThreadResultVO {
private boolean success;
private Object result;
private String exception;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
public String getException() {
return exception;
}
public void setException(String exception) {
this.exception = exception;
}
}
5、线程池的使用
public static void main(String[] args) {
//需要处理的数据
List<ArrayList<String>> dataList = new ArrayList<>(0);
//调用的服务——暂时通过new的方式创建(可以使用spring的方式创建)
IntentionVipService intentionVipService = new IntentionVipService();
//调用服务获得批次号
String batchNum = intentionVipService.getIntentionVipBatchNum();
//创建一个自定义的线程池,线程池的大小为5,核心线程个数也为5
CustomThreadPool customThreadPool = new CustomThreadPool(5);
//执行上传操作
List<Future<ThreadResultVO>> dealTask = customThreadPool.executeObject(dataList, 100, TaskManager.class, "dealTask", "201800045864",batchNum,intentionVipService);
//得到处理的数据
List<ArrayList<String>> errdataList = new ArrayList<>(0);
for (Future<ThreadResultVO> item : dealTask) {
try {
List<ArrayList<String>> temp = (List<ArrayList<String>>)item.get().getResult();
errdataList.addAll(temp);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}