第一步:定义任务接口 IExecuteRun.java
package gov.services.result.multithreading;
import java.util.Map;
/**
*
*
* <p>
* 任务接口
* </p>
* <p>
* Copyright:2015.All rights reserved.
* </p>
* <p>
* Company:Zsoft
* </p>
* <p>
* CreateDate: 2019年9月21日 上午9:33:05
* </p>
* @author YuGongWen
* @history Mender: YuGongWen;Date: 2019年9月21日 上午9:33:05;
*/
public interface IExecuteRun {
/**
* 需要执行的任务
* @param propertiesMap
*/
public void execute(Map<String,Object> propertiesMap);
}
第二步: 定义公共线程类 CommonRunTask.java
package gov.services.result.multithreading;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
/**
*
* <p>
* 公共线程类
* </p>
* <p>
* Copyright:2015.All rights reserved.
* </p>
* <p>
* Company:Zsoft
* </p>
* <p>
* CreateDate: 2019年9月19日 下午12:02:42
* </p>
* @author YuGongWen
* @history Mender: YuGongWen;Date: 2019年9月19日 下午12:02:42;
*/
public class CommonRunTask<T extends IExecuteRun> implements Runnable {
private static Logger logger = Logger.getLogger(CommonRunTask.class);
private Class<T> targetClass = null;
/**
* 执行任务需要的参数map
*/
private Map<String,Object> propertiesMap = new HashMap<String,Object>();
public CommonRunTask(Class<T> calss,Map<String,Object> propertiesMap) {
super();
this.targetClass = calss;
this.propertiesMap = propertiesMap;
}
@Override
public void run() {
T run = null;
try {
run = targetClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
logger.error("无法给类创建实例,请检查! ",e);
} catch (IllegalAccessException e) {
e.printStackTrace();
logger.error("非法访问异常,请检查!",e);
}
try {
run.execute(propertiesMap);
} catch (Exception e) {
e.printStackTrace();
logger.error("线程池在执行任务时发生异常,请检查!",e);
}
}
}
第三步: 利用单例模式创建线程池 ThreadPoolSingle.java
package gov.services.result.multithreading;
import gov.platform.core.Configuration;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.log4j.Logger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
/**
*
* <p>
* 全局线程池
* </p>
* <p>
* Copyright:2015.All rights reserved.
* </p>
* <p>
* Company:Zsoft
* </p>
* <p>
* CreateDate: 2019年9月3日 上午12:24:20
* </p>
* @author YuGongWen
* @history Mender: YuGongWen;Date: 2019年9月3日 上午12:24:20;
*/
public class ThreadPoolSingle {
private static Logger logger = Logger.getLogger(ThreadPoolSingle.class);
/**
* 默认线程池容量为 10
*/
private static final Integer DEFAULT_POOL_SIZE = 10;
private static ExecutorService fixedThreadPool = null;
private ThreadPoolSingle() {}
public static synchronized ExecutorService getInstance() {
if(fixedThreadPool == null) {
fixedThreadPool = Executors.newFixedThreadPool(getPoolSizeNumber());
}
return fixedThreadPool;
}
/**
* 从配置文件中获取线程池数量的配置,若无配置,将采用默认配置<BR/>
* @return
*/
public static Integer getPoolSizeNumber() {
Integer return_integer = 0;
try {
String numStr = Configuration.getProperty("Overall.Thread.Pool.Size");
return_integer = Integer.valueOf(numStr);
// 设置安全值,防止用户设置的数值过大,造成系统资源异常
if(return_integer > 50 || return_integer < 1) {
logger.error("从配置文件中获取线程池数量时发生错误,请检查配置(Overall.Thread.Pool.Size)是否超出《1-50》的范围。若超出,将采用系统默认配置!");
return_integer = DEFAULT_POOL_SIZE;
}
} catch (Exception e) {
e.printStackTrace();
return_integer = DEFAULT_POOL_SIZE;
logger.error("从配置文件中获取线程池数量时发生异常,请检查配置(Overall.Thread.Pool.Size)是否正确。若无配置或配置错误,将采用系统默认配置!",e);
}
logger.debug("全局线程池容量为: "+ return_integer);
return return_integer;
}
/**
* 输出线程池当前使用状态<BR/>
* 建议每次往线程池中增加任务时,调用此方法。用来监控线程池使用情况,通过查看一段时间内的日志,根据线程池使用情况,判断是否需要增加线程池容量。<BR/>
* 当系统运行时,若大部分时候 排队任务数 > 线程池最大线程数量 * 2 ,建议增加线程池容量<BR/>
* 当系统运行时,若大部分时候 排队任务数 < 线程池最大线程数量 / 2 ,建议减少线程池容量<BR/>
* @param if_debug_level 当此参数为 true时,则按照debug级别输出日志。
* @return
*/
public static String printThreadPoolSingleStatus(Boolean if_debug_level) {
if(fixedThreadPool != null){
try {
ThreadPoolExecutor pool = ((ThreadPoolExecutor) fixedThreadPool);
int queueSize = pool.getQueue().size();
int activeCount = pool.getActiveCount();
int poolSize = pool.getPoolSize();
long completedTaskCount = pool.getCompletedTaskCount();
long taskCount = pool.getTaskCount();
StringBuilder sb = new StringBuilder("全局线程池使用情况======");
sb.append("线程池最大线程数量:").append(poolSize);
sb.append(",当前排队任务数:").append(queueSize);
sb.append(",当前活动任务数:").append(activeCount);
sb.append(",执行完成任务数:").append(completedTaskCount);
sb.append(",总任务数:").append(taskCount);
if(BooleanUtils.isTrue(if_debug_level)){
logger.debug(sb.toString());
}else{
logger.info(sb.toString());
}
}catch (Exception e){
e.printStackTrace();
logger.error("输出线程池使用状态发生异常",e);
}
}
return "线程池未初始化、实例对象为空,无法输出线程池使用状态!";
}
}
注意: Configuration.java 为系统读取、存储 properties 配置参数的工具类。
第四步: 定义具体线程需要执行的任务 TestRun.java
package gov.zhbs.multitaskrun.other;
import gov.services.result.multithreading.IExecuteRun;
import org.apache.log4j.Logger;
import java.util.Map;
/**
* <p>
* 测试线程池
* </p>
* <p>
* Copyright:.All rights reserved.
* </p>
* <p>
* Company:Zsoft
* </p>
* <p>
* CreateDate: 2020/8/17
* </p>
*
* @author YuGongWen
* @history Mender: YuGongWen;Date: 2020/8/17;
*/
public class TestRun implements IExecuteRun{
private static Logger logger = Logger.getLogger(TestRun.class);
@Override
public void execute(Map<String,Object> propertiesMap) {
// ExGdbsSbService exGdbsSbService = (ExGdbsSbService) propertiesMap.get("exGdbsSbService");
Integer paramAge = (Integer) propertiesMap.get("paramAge");
System.out.println("(代码标识号: GZ-ZHBS-3976223783992743)paramAge = " + paramAge);
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(2*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.debug("线程名: "+ Thread.currentThread().getName() + ",当前执行: " + String.valueOf(i+1));
}
}
}
第五步: 在业务代码中开启线程任务
package gov.zhbs.multitaskrun.other;
import gov.services.result.multithreading.CommonRunTask;
import gov.services.result.multithreading.ThreadPoolSingle;
import java.util.HashMap;
import java.util.Map;
/**
* <p>
* xxxxx
* </p>
* <p>
* Copyright:2021.All rights reserved.
* </p>
* <p>
* Company:Zsoft
* </p>
* <p>
* CreateDate:2021-07-30 09:21
* </p>
*
* @author YuGongWen
* @history Mender:YuGongWen;Date:2021-07-30 09:21;
*/
public class TestMain {
public static void main(String[] args) {
/**
* 开启多线程执行xxxx任务
*/
Map<String,Object> propertiesMapV2 = new HashMap<>();
// propertiesMapV2.put("exGdbsSbService", exGdbsSbService);// 可以传递service参数
propertiesMapV2.put("paramAge", 22);
ThreadPoolSingle.getInstance().execute(new CommonRunTask<TestRun>(TestRun.class, propertiesMapV2));
}
}
至此,关于Java单例模式线程池的应用的介绍结束。