java实现(并行)异步编程小框架
- 其实市面上异步编程框架项目挺多的,而为啥又单独搞一个,因为我真的闲得很。
- 其次出于学习和提升自己的原因
- 想保留原有的同步编程风格,又想实现异步执行的效果
- 想用最简单的代码实现异步编程,又想自己掌握定义权
技术选型和架构
采用线程池+注解(其实整体架构真的很简单)
整体架构可分为线程池构造和异步任务
1-ExecutorComponent(线程池对象)
2-通过TaskMode和JobMode(异步任务对象)
安装教程
-
方式一:下载项目源码整合进项目
-
方式二:下载项目源码打成jar包,放入lib目录下,通过pom.xml引入
<dependency> <groupId>com.hxz</groupId> <artifactId>djybkj</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/lib/djybkj-1.0-SNAPSHOT.jar</systemPath> </dependency>
使用说明
- 可以自己手动创建ExecutorComponent(线程池对象)
也可以spring注解注入ExecutorComponent(线程池对象)
//通过spring @Configuration 方式实现ExecutorComponent(线程池对象)创建和注入
@Bean("executorComponent")
public ExecutorComponent executorComponent(){
/**
* 采用默认配置
* 1-通过InitExcutorMode(内置线程池的实现)
*/
//return new ExecutorComponent(new InitExcutorMode(),new RunJkDoPlayTaskImp(){});
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
/**
* 采用自定义配置的方式(支持线程池自定义的方式)
* 1-通过InitExcutorMode可以自定义线程池的属性配置
* 2-也通过复写ExecutorComponent的CreateExecutor函数实现线程池的自定义创建
*/
return new ExecutorComponent(new InitExcutorMode().setCorePoolSize(50).setMaximumPoolSize(50).setKeepAliveTime(60).setUnit(TimeUnit.SECONDS).setWorkQueue(new LinkedBlockingDeque<>()), new RunJkDoPlayTaskImp(){}){
@Override
public ThreadPoolExecutor CreateExecutor(InitExcutorMode initExcutorMode) {//建议使用无边界队列,有边界队列需要自己把握任务数量和线程数量的比例,容易出现队列溢出现象(很容易抛异常)
if(null==initExcutorMode.getHandler()){
return new ThreadPoolExecutor(initExcutorMode.getCorePoolSize(),initExcutorMode.getMaximumPoolSize(),initExcutorMode.getKeepAliveTime(),initExcutorMode.getUnit(),initExcutorMode.getWorkQueue()){
protected void beforeExecute(Thread t,Runnable r) {
System.out.println("准备执行:"+ ((ParameterJk)r).getId());
}
protected void afterExecute(Runnable r,Throwable t) {
System.out.println("执行完毕:"+((ParameterJk)r).getId());
}
protected void terminated() {
System.out.println("线程池退出");
}
};
}else{
return new ThreadPoolExecutor(initExcutorMode.getCorePoolSize(),initExcutorMode.getMaximumPoolSize(),initExcutorMode.getKeepAliveTime(),initExcutorMode.getUnit(),initExcutorMode.getWorkQueue(),initExcutorMode.getHandler()){
protected void beforeExecute(Thread t,Runnable r) {
System.out.println("准备执行:"+ ((ParameterJk)r).getId());
}
protected void afterExecute(Runnable r,Throwable t) {
System.out.println("执行完毕:"+((ParameterJk)r).getId());
}
protected void terminated() {
System.out.println("线程池退出");
}
};
}
}
};
}
- 假设你有两个Service实现类(业务服务类)
1-Service实现类实现接口JobJk
2-Service函数用注解@HxzMethod修饰并给定本对象内唯一id
import com.hxz.djbxkj.HxzExecutor.ExecutorCode.JobJk;
import com.hxz.djbxkj.HxzExecutor.annotation.HxzMethod;
import org.springframework.stereotype.Service;
@Service("domeRw")
public class DomeRw implements JobJk {
@HxzMethod(id="doPlay")
public void doPlay(String a){
System.out.println("domeRw------>"+a);
}
@HxzMethod(id="doPlay-2")
public int doPlay2(int a,int b){
System.out.println(a+"+"+b+"="+(a+b));
return a;
}
}
import com.hxz.djbxkj.HxzExecutor.ExecutorCode.JobJk;
import com.hxz.djbxkj.HxzExecutor.annotation.HxzMethod;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service("testRw")
public class TestRw implements JobJk {
@HxzMethod(id="doPlay-01")
public A doPlay(String a, int[] b, Map<String,Object> c){
System.out.println("testRw------------->"+a);
for(int i:b){
System.out.println("testRw------------->"+i);
}
for(String k:c.keySet()){
System.out.println("testRw------------->"+k);
}
return new A();
}
@HxzMethod(id="doPlay-02")
public String doPlay2(String a, int[] b, Map<String,Object> c){
System.out.println(a);
for(int i:b){
System.out.println(i);
}
for(String k:c.keySet()){
System.out.println(k);
}
return null;
}
}
- 通过TaskMode和JobMode实现异步编程
1-TaskMode(String name,JobMode[] jobModes)(任务名称、异步任务数组)
2-JobMode(JobJk,ParameterMode,id,name,AopJk)- JobJk:实现JobJk接口的Service实现类(业务服务类)【必须属性】
- ParameterMode:Service实现类(业务服务类)内被@HxzMethod修饰函数的参数列表【必须属性】
- id:Service实现类(业务服务类)内被@HxzMethod修饰函数的id【必须属性】
- name:异步任务异步任务名称【必须属性】
- AopJk:切面接口,可实现对Service实现类(业务服务类)的功能增强【可选属性】
- 以下是异步编程具体实现例子
@Autowired
private DomeRw domeRw;
@Autowired
private TestRw testRw;
@Autowired
private ExecutorComponent executorComponent;
//-----以下是实现代码
Map<String,Object> c=new HashMap<>();//testRw
c.put("idx","idx");
TaskMode tm=new TaskMode("我是异步任务的名字",
new JobMode[]{
new JobMode(domeRw, new ParameterMode(1, 2), "doPlay-2", "DomeRw", new AopJk() {
@Override
public void befor(JobMode jobMode) {
System.out.println(jobMode.getName()+"=="+jobMode.getId()+":我准备动了");
}
@Override
public void after(Object o, JobMode jobMode) {
System.out.println(jobMode.getName()+"=="+jobMode.getId()+":我动完了");
}
@Override
public void errer(Exception e, JobMode jobMode) {
}
}),
new JobMode<A>(testRw,new ParameterMode("我是string类型的参数",new int[]{1,2,3},c),"doPlay-01","TestRw")});
//开启异步任务
tm=executorComponent.doPlay(tm); //执行异步编程【主线程会在此被阻塞】
//--------------------------------------------------------------------
/**
* TaskMode:默认与主线程保持同步
* 如果通过TaskMode.setSynchroniz(false);//设置为false后,开启异步
* 必须在executorComponent.doPlay(tm);之前设置
* 如果你想在executorComponent.doPlay(tm);之后又保持主线程阻塞等待的
* 可以通过TaskMode.endTask(tm);使主线程又进入等待状态,否则主线程跟异步任务是保持异步的
*/
//tm.setSynchroniz(false);//设置为异步--【注意】:默认是同步步
//tm=executorComponent.doPlay(tm);
//-------置入业务----------
//tm.endTask(tm);//主线程又进入等待状态
//--------------------------------------------------------------------
System.out.println("主线程-运行状态:"+tm.getState());
System.out.println("主线程-错误日志:"+tm.getMeg());
System.out.println("主线程-运行耗时:"+tm.getHs());
for(JobMode jm:tm.getJobModeS()){
System.out.println(jm.getName()+"-运行状态:"+jm.getState());
System.out.println(jm.getName()+"-错误日志:"+jm.getMeg());
System.out.println(jm.getName()+"-运行耗时:"+jm.getHs());
System.out.println(jm.getName()+"-运行结果:"+jm.getResult());
}
请戳这里:源码下载地址