第一步:定義任務接口 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單例模式線程池的應用的介紹結束。