AsyncTask -- Java Asynchronous Call Framework

Keywords: Java git Database Mybatis

Copyright Statement: This article is the original article of the blogger. It can not be reproduced without the permission of the blogger.

Catalog (?)[-]

  1. Original article reprinted please indicate author jmppok and source HTTP blog csdnnet jmppokarticledetails 44590991
  2. AsyncTask is a Java asynchronous invocation framework written by individuals to support users
  3. Why does AsyncTask differ from Asyn4J
    1. 1 Java's traditional Thread and Runable functionality is inadequate
    2. 2 Asyn4J
  4. Design and Implementation
    1. 1 interface design
    2. 2 Code Implementation
  5. test
    1. 1 custom MyTask
    2. 2 Customize MyTaskExecutor
    3. 3 Configure MyTaskExecutor
    4. 4 Submit Task and monitor progress in real time
    5. 5 Terminate Task execution and restart the program for Task recovery testing
  6. insufficient

Original article, reproduced please specify the author: jmppok and origin: http://blog.csdn.net/jmppok/article/details/44590991.



AsyncTask is a Java asynchronous invocation framework written by individuals to support users:

1) Customize Task, and set Task's type (Type), subType (subType), time out (TImeout), flag (Flag - can be used to distinguish different Tasks), Task's input parameters (input), etc.

2) Submit to the framework for asynchronous execution through submitTask. The framework finds the corresponding Task Exectuor and executes with multi-threads.

3) TaskExecutor can be customized and added to the framework through configuration. TaskExecutor supports Execotor Chain, and multiple Executors can be combined to execute sequentially. It also supports real-time notification of Task status and progress during Task execution.

4) Users can use Task Collector to query all Tasks through Task Manager. Task Collector supports combinatorial queries by Task Id, Task Type, Task SubType, Task State, Task Flag, Task beginTIme, Task finishTime, etc.

5) Supporting persistence, user-submitted Task s can be stored in data base Medium. Even if Task is interrupted during execution, it will resume execution after restarting from the database.

6) Users can get the reference ITaskReference of Task through the query interface, and the status and Progress of Task can be obtained in real time through ITaskReference.

7) The user can define the FinishedCallBack callback of Task, which is passed in at Submit Task and automatically callback after Task is completed.

8) Support users to use it synchronously through waitForTask of ITaskReference.

9) Users can obtain Task execution results or error information through ITaskReference.


Code: https://git.oschina.net/jmpp/AsyncTask


1. Why do you need AsyncTask? Is it different from Asyn4J?

1.1 Java's traditional Thread and Runable functionality is inadequate

Java Thread, ThreadPool and other multi-threaded programming interfaces are provided. But these are all basic interfaces, although easy to use, but the function is relatively simple, many scenarios can not meet the needs.

For example, the following scenarios:

1) I need to submit a task, change the task to be executed asynchronously in the background, and at the same time I need to observe the status and progress of the task in real time.

2) When submitting a task, I hope to pass in parameters. When the task is completed, I can actively notify me and get the results.

3) Task persistence, I hope that after the completion of the task, you can query the list of tasks executed. Or the task can be re-executed if it fails.

If these scenarios are to be implemented, Java's own interfaces are obviously not satisfied, and a new framework is needed to implement them.


1.2 Asyn4J

Asyn4J is a similar framework, but it does not currently support tasks such as timeout, persistence, task callback and so on.



2. Design and Implementation

2.1 Interface Design

Direct drawing


2.2 Code Implementation

See Specific Implementation Code Git@OSChttps://git.oschina.net/jmpp/AsyncTask

The code structure is as follows:


Here is a brief description of the realization of ideas:

1) The whole implementation is based on Java Thread and ThreadPool, without using a third-party framework.

2) Persistence is based on MySQL There is only one database table task, see tasks.sql.

3) The implementation of persistence layer uses Mybatis, which gives Mybatis a code generation tool and directly generates the corresponding task table. data structure.

4) Object serialization is necessary for persistence. Kryo is used here. Why Kryo? See my other article: Summary of Java Object Serialization.

5) Log4j is used in the log.


3. test

Specifically visible code: https://git.oschina.net/jmpp/AsyncTask

3.1 Custom MyTask

  1. package test.mytask;  
  2.   
  3. import com.lenovo.asynctask.Task;  
  4.   
  5. /** 
  6.  * Class MyTask Implementation Description: TODO Class Implementation Description 
  7.  *  
  8.  * @author ligh4 2015 12 March 2000, 2:42:56 p.m. 
  9.  */  
  10. public class MyTask extends Task {  
  11.   
  12.     /** 
  13.      * @param taskType 
  14.      * @param inputParam 
  15.      * @param timeoutMills 
  16.      */  
  17.     public MyTask(Object inputParam, int timeoutMills) {  
  18.         super(MyTask.class.getSimpleName(), inputParam, timeoutMills);  
  19.         setNeedPersistence(true);  
  20.     }  
  21.   
  22. }  


3.2 Custom MyTaskExecutor

  1. package test.mytask;  
  2.   
  3. import com.lenovo.asynctask.ITaskExecutor;  
  4. import com.lenovo.asynctask.ITaskReferenceInternal;  
  5. import com.lenovo.asynctask.TaskState;  
  6. import com.lenovo.asynctask.util.LogHelper;  
  7.   
  8. /** 
  9.  * Class TestTaskExecutor Implementation Description: TODO Class Implementation Description 
  10.  *  
  11.  * @author ligh4 2015 March 12, 2000, 2:43:19 p.m. 
  12.  */  
  13. public class MyTaskExecutor extends ITaskExecutor {  
  14.   
  15.     /** 
  16.      * @author ligh4 2015 March 12, 2000, 2:46:51 p.m. 
  17.      */  
  18.     @Override  
  19.     public Object execute(ITaskReferenceInternal taskRef) {  
  20.         LogHelper.debug("begin execute MyTask...");  
  21.   
  22.         for (int i = 0; i < 100; i++) {  
  23.             try {  
  24.                 Thread.sleep(1000);  
  25.             } catch (Exception e) {  
  26.                 LogHelper.exception(e);  
  27.             }  
  28.             taskRef.setProgress(i + 1);  
  29.         }  
  30.   
  31.         return taskRef.getInput().toString().toUpperCase();  
  32.     }  
  33.   
  34.     /** 
  35.      * @author ligh4 2015 March 12, 2000, 2:46:51 p.m. 
  36.      */  
  37.     @Override  
  38.     public Object continue_execute(ITaskReferenceInternal taskRef) {  
  39.         if (taskRef.getState() == TaskState.running) {  
  40.             int i = taskRef.getProgress();  
  41.             for (; i < 100; i++) {  
  42.                 try {  
  43.                     Thread.sleep(1000);  
  44.                 } catch (Exception e) {  
  45.                     LogHelper.exception(e);  
  46.                 }  
  47.                 taskRef.setProgress(i + 1);  
  48.             }  
  49.   
  50.             return taskRef.getInput().toString().toUpperCase();  
  51.         } else {  
  52.             taskRef.setState(TaskState.failed, "");  
  53.             return null;  
  54.         }  
  55.   
  56.     }  
  57.   
  58. }  


3.3 Configuration of MyTaskExecutor

Add in taskexecutors.properties:

  1. MyTask = test.mytask.MyTaskExecutor  

It's actually the type of task = Executor of task.

3.4 Submit Task and monitor progress in real time

  1. package test.mytask;  
  2.   
  3. import java.util.List;  
  4.   
  5. import com.lenovo.asynctask.ITaskFinishedCallback;  
  6. import com.lenovo.asynctask.ITaskReference;  
  7. import com.lenovo.asynctask.TaskCollector;  
  8. import com.lenovo.asynctask.TaskManager;  
  9. import com.lenovo.asynctask.TaskState;  
  10. import com.lenovo.asynctask.util.DateUtil;  
  11. import com.lenovo.asynctask.util.LogHelper;  
  12.   
  13. /** 
  14.  * Class TestContinueTask Implementation Description: TODO Class Implementation Description 
  15.  *  
  16.  * @author ligh4 2015 March 23, 2000, 9:42:14 a.m. 
  17.  */  
  18. public class TestContinueTask {  
  19.   
  20.     /** 
  21.      * @author ligh4 2015 March 12, 2000, 2:52:45 p.m. 
  22.      * @param args 
  23.      */  
  24.     public static void main(String[] args) throws Exception {  
  25.         TaskManager.instance().start();  
  26.   
  27.         List<ITaskReference> tasks = queryRunningTasks();  
  28.         if (tasks == null || tasks.size() == 0) {  
  29.             submitAndWaitTask();  
  30.         } else {  
  31.             for (ITaskReference taskReference : tasks) {  
  32.                 queryTaskProgress(taskReference);  
  33.             }  
  34.         }  
  35.   
  36.         TaskManager.instance().stop();  
  37.     }  
  38.   
  39.     public static void submitAndWaitTask() throws Exception {  
  40.         MyTask task = new MyTask("liguanghui"200000);  
  41.         ITaskReference taskReference = TaskManager.instance().submitTask(task,  
  42.                 new ITaskFinishedCallback() {  
  43.   
  44.                     @Override  
  45.                     public void onTaskFinished(ITaskReference taskRef) {  
  46.                         LogHelper.debug(taskRef.getId() + ";" + taskRef.getState().toString() + ";"  
  47.                                 + DateUtil.format(taskRef.getStartedTime()) + "  "  
  48.                                 + DateUtil.format(taskRef.getFinishedTime()) + ";"  
  49.                                 + taskRef.getResult().toString());  
  50.   
  51.                     }  
  52.                 });  
  53.   
  54.         queryTaskProgress(taskReference);  
  55.     }  
  56.   
  57.     public static void queryTaskProgress(ITaskReference taskReference) throws Exception {  
  58.         String taskID = taskReference.getId();  
  59.         while (!taskReference.isFinished()) {  
  60.             LogHelper.debug(taskID + ": progress " + taskReference.getProgress());  
  61.             Thread.sleep(1000);  
  62.         }  
  63.         LogHelper.debug(taskID + ": finished. ");  
  64.     }  
  65.   
  66.     public static List<ITaskReference> queryRunningTasks() {  
  67.         TaskCollector collector = new TaskCollector();  
  68.         collector.setTaskStateFilter(new TaskState[] { TaskState.running });  
  69.         collector.setTaskTypeFilter(new String[] { MyTask.class.getSimpleName() });  
  70.         return TaskManager.instance().findTasks(collector);  
  71.   
  72.     }  
  73. }  


3.5 Terminate Task execution and restart the program for Task recovery testing

Or the same code as 3.4

1) Task is not available for the first run, and a Task is submitted. submitAndWaitTask();

2) If the change Task is terminated without being executed, the Task will be restored after the second boot.

3) At this point query Running Tasks will query the running Task and progress to the branch waiting for the Task.

4) Of course, if you stop for a long time before restarting, you will find that Task timeout.

4. deficiency

1. The overall implementation is relatively simple, especially in the database table to store Java object serialization fields, lazy varchar(2000), may exceed, preferably blob. (Why didn't you use Blob at that time, because of laziness, if Blob, mybatis generated more complex code, there will be a XXwithBlob, inconvenient calls....)

2. The number of thread pools is dead and should be configurable.

3.test It's relatively simple. There may be unknown bug s.


Posted by dabaR on Mon, 08 Apr 2019 21:15:31 -0700