Multithreaded task design

/**

*Task management class

*/

public class TaskManager {

 

/**

* Log processing class

*/

private static Log logger = LogFactory.getLog(TaskManager.class);

 

/**

* Thread pool task execution object

*/

private ThreadPoolTaskExecutor taskExecutor;

 

/**

* Where to save the task results

*/

private final static String resultSavePath = Constants.getDownloadPath()

+ File.separator + Constants.get(Constants.TASK_TEMP_PATH);

 

/**

* The file name of the task execution result serialized into a file

*/

private static final String RESULT_FILE_NAME = "result";

 

/**

* The name of the directory where the files generated during task execution are saved

*/

private static final String FILES_DIR = "files";

 

/**

* Add the task to the thread pool

* @param task task object

* @param params parameters required to execute the task

* @param operatorId The current operator ID

* @return If the addition is successful, return the task number, if the server is busy, return null

*/

public String addTask(AbstractTask task, Map<String, Object> params, String operatorId) {

if (resultSavePath == null || resultSavePath.length() < 1) {

if (logger.isErrorEnabled()) {

logger.error("The save directory is not configured");

}

return null;

}

//If the save directory does not exist, this directory will be created automatically

File saveDir = new File (resultSavePath);

if (!saveDir.exists()) {

saveDir.mkdirs ();

if (saveDir.exists()) {

if (logger.isDebugEnabled()) {

logger.debug("Successfully created save directory");

}

} else {

if (logger.isErrorEnabled()) {

logger.error("Error in configuration directory");

return null;

}

}

}

 

//if the thread pool is full

if (taskExecutor.getThreadPoolExecutor().getQueue().remainingCapacity() == 0) {

return null;

}

//Set the parameters required when the task is executed

task.setParams(params);

//generate task number

String taskId = generateTaskId(operatorId);

/ / Create the file storage directory generated when the task is executed

String savePath = resultSavePath + File.separator + taskId + File.separator + FILES_DIR + File.separator;

createDir(savePath);

/ / Set the file storage directory generated when the task is executed

task.setSavePath (savePath);

//create task thread object

TaskThread t = new TaskThread(taskId, task);

//Add the task to the connection pool

taskExecutor.execute(t);

return taskId;

}

 

/**

* Get the result of the task execution

* @param taskId task number

* @return if the result does not exist, return null, otherwise return the result object

* @throws IOException 

*/

public TaskResult getTaskResult(String taskId) throws IOException {

File resultFile = new File(resultSavePath + File.separator + taskId + File.separator + RESULT_FILE_NAME + File.separator + RESULT_FILE_NAME);

if (!resultFile.exists()) {//If the result file does not exist

return null;

}

 

FileInputStream fis = new FileInputStream(resultFile);

ObjectInputStream ois = new ObjectInputStream(fis);

try {

Object obj = ois.readObject();

ois.close();

fis.close();

if (obj == null) {//If the read result is empty, return null

logger.info("result File content is null!");

return null;

} else {

TaskResult result = (TaskResult) obj;

return result;

}

} catch (ClassNotFoundException e) {

throw new RuntimeException(e);

} finally {

if (ois != null) {

ois.close();

}

if (fis != null) {

fis.close();

}

}

}

 

/**

* Get files generated during task execution

* @param taskId task number

* @param fileName The file name to be taken

* @return If the result does not exist, return null, otherwise return the file object

* @throws IOException 

*/

public File getTaskResultFile(String taskId, String fileName) throws IOException {

File reportFile = new File(resultSavePath + File.separator + taskId + File.separator + FILES_DIR + File.separator + fileName);

if (!reportFile.exists()) {//If the file does not exist

File resultFile = new File(resultSavePath + File.separator + taskId + File.separator + RESULT_FILE_NAME + File.separator + RESULT_FILE_NAME);

FileInputStream fis = new FileInputStream(resultFile);

ObjectInputStream ois = new ObjectInputStream(fis);

try {

Object obj = ois.readObject();

ois.close();

fis.close();

if (obj == null) {//If the read result is empty, return null

logger.info("result File content is null!");

return null;

} else {

TaskResult result = (TaskResult) obj;

logger.error("task " + result.getTaskClassName() + " not generate report file!");

}

} catch (ClassNotFoundException e) {

throw new RuntimeException(e);

} finally {

if (ois != null) {

ois.close();

}

if (fis != null) {

fis.close();

}

}

return null;

}

return reportFile;

}

 

/**

* Create directory - supports multiple levels

* @param path the path to the directory

*/

private void createDir(String path) {

File dir = new File(path);

dir.mkdirs();

}

 

/**

* Generate a unique number for the task

* @param operatorId current operator

* @return returns the generated number

*/

private String generateTaskId(String operatorId) {

Date now = new Date();

SimpleDateFormat sdf = new SimpleDateFormat(Constants.YYYY_MM_DD_SSS);

if (operatorId == null || operatorId.length() < 1) {

return sdf.format(now) + Toolkit.getUuidRandomizer().generate();

} else {

return sdf.format(now) + operatorId + Toolkit.getUuidRandomizer().generate();

}

}

 

public void setTaskExecutor(ThreadPoolTaskExecutor taskExecutor) {

this.taskExecutor = taskExecutor;

}

 

/**

* The task thread object that encapsulates the task

* @author oscar.xie

*

*/

private class TaskThread implements Runnable {

/**

* Task number - assigned by task manager

*/

private String taskId;

 

/**

* task object

*/

private AbstractTask task;

 

public TaskThread(String taskId, AbstractTask task) {

this.taskId = taskId;

this.task = task;

}

 

/**

* Task execution method

*/

public void run() {

TaskResult result = task.execute();

if (result != null) {

result.setTaskClassName(task.getClass().getName());

String savePath = resultSavePath + File.separator + this.taskId + File.separator + RESULT_FILE_NAME;

createDir(savePath);

File resultFile = new File(savePath + File.separator + RESULT_FILE_NAME);

FileOutputStream fos = null;

ObjectOutputStream east = null;

try {

fos = new FileOutputStream(resultFile);

oos = new ObjectOutputStream (fos);

oos.writeObject(result);

oos.flush ();

} catch (Exception e) { //This exception generally does not occur

logger.error("write task result File failure:" + e.getMessage());

} finally {

try {

if (oos != null) {

oos.close();

}

if (fos != null) {

fos.close();

}

} catch (Exception e) {

throw new RuntimeException(e);

}

}

} else {

logger.info("result is null************************************!");

}

}

}

}

</div>

<div>

<!-- Asynchronous task thread operation configuration-->

<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">

<property name="corePoolSize" value="30" /> <!-- Core thread pool size -->

<property name="keepAliveSeconds" value="200" /> <!-- seconds to keep alive -->

<property name="maxPoolSize" value="35" /> <!-- Maximum thread pool size -->

<property name="queueCapacity" value="1" /> <!-- Waiting queue size -->

</bean>

 

<!-- Asynchronous Task Manager -->

<bean id="taskManager" class="com.sf.module.bilcommon.util.TaskManager">

<property name="taskExecutor" ref="threadPoolTaskExecutor"></property>

</bean>

 

 

/**

 * Abstract task class - used for long-running business operations

 * @author oscar.xie

 *

 */

public abstract class AbstractTask {

 

/**

* Required parameters for task execution

*/

protected Map<String, Object> params;

 

/**

* The storage directory of files generated during task execution

*/

protected String savePath;

 

/**

* The task action to perform

* @return the result object of the execution

*/

public abstract TaskResult execute();

 

public Map<String, Object> getParams() {

return params;

}

 

public void setParams(Map<String, Object> params) {

this.params = params;

}

 

public void setSavePath(String savePath) {

this.savePath = savePath;

}

}

 

 

/**

 * The result class of task execution

 * @author oscar.xie

 *

 */

public class TaskResult implements Serializable {

 

private static final long serialVersionUID = -4396986540034886297L;

 

/**

* Whether the task was successfully executed

*/

private Boolean success;

 

/**

* The result of the task execution

*/

private String result;

 

/**

* The class name of the task execution - used to find the processing class when an error occurs

*/

private String taskClassName;

 

public TaskResult () {

 

}

 

public TaskResult(Boolean success, String result) {

this.success = success;

this.result = result;

}

 

public String getResult() {

return result;

}

 

public void setResult(String result) {

this.result = result;

}

 

public Boolean getSuccess() {

return success;

}

 

public void setSuccess(Boolean success) {

this.success = success;

}

 

public String getTaskClassName() {

return taskClassName;

}

 

public void setTaskClassName(String taskClassName) {

this.taskClassName = taskClassName;

}

}

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326585493&siteId=291194637