前言:在实际的开发过程中,队列+多线程+监听器的方式,适用于在批量新增或更新一张表A的数据时,可以同步批量新增或更新另一张表B的数据,尤其是在数据量比较大的时候,这种方式起到了很好的缓冲作用,并且使得模块之间耦合度大大降低,扩展性较好。
第一步:自定义对象(批量)事件(一般定义在子模块)
package cn.springcloud.book.common.test;
import java.util.List;
import org.springframework.context.ApplicationEvent;
/**
* 定义对象事件
* @author prd-hushanlin
*/
public class ObjectEvent extends ApplicationEvent
{
/**
* 需要实时同步的数据(Object可替换成需要的对象)
*/
private List<Object> list;
public ObjectEvent(Object source, List<Object> list)
{
super(source);
this.list = list;
}
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
}
第二步:自定义对象存储队列(一般定义在子模块)
package cn.springcloud.book.common.test;
import java.util.List;
import java.util.Vector;
/**
* @className: MtPlanMainQueue
* @description: TODO 类描述
**/
public class MtPlanMainQueue
{
private static MtPlanMainQueue instance = null;
// 实际存放转换对象信息的队列,采用线程安全的Vercor容器
protected static Vector<Object> taskQueue = new Vector<Object>();
private MtPlanMainQueue()
{
}
public static MtPlanMainQueue getInstance()
{
if (instance == null)
{
instance = new MtPlanMainQueue();
}
return instance;
}
/**
* 向队列中添加对象
* @param info
*/
public static void add(Object info)
{
taskQueue.add(info);
}
/**
* 从队列中删除对象
* @param info
*/
public static void remove(Object info)
{
if (taskQueue.size() > 0)
{
taskQueue.remove(info);
}
}
/**
* 队列批量添加
* @param infoList
*/
public static void addAll(List<Object> infoList)
{
taskQueue.addAll(infoList);
}
}
第三步:自定义线程方法类(一般定义在父级模块)
package cn.springcloud.book.common.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 自定义同步线程
* @author smr
*/
public class MtPlanMainExecutorService
{
/** 日志信息 **/
private static Logger lOG = LoggerFactory.getLogger(MtPlanMainExecutorService.class);
private final ExecutorService pool;
private static MtPlanMainExecutorService instance = null;
// 线程池大小,即每次最多允许开启几个线程执行转换操作
private static final int THREAD_SIZE = 5;
/**
* 单例方式
* @return
*/
public static synchronized MtPlanMainExecutorService getInstance()
{
if (instance == null)
{
instance = new MtPlanMainExecutorService();
}
return instance;
}
private MtPlanMainExecutorService()
{
pool = Executors.newFixedThreadPool(THREAD_SIZE);
}
/**
* 线程执行
* @param plan
*/
@SuppressWarnings("unchecked")
public void execute(Object plan)
{
try
{
pool.submit(new ObjectCallable(plan));
}
catch (Exception e)
{
lOG.error("{}", "线程执行", e.getMessage());
}
}
/** 这里还可以定义其他的线程执行方法,放置不同的实例对象 **/
/**
* 关闭线程
* @param plan
*/
public synchronized void shutdown()
{
pool.shutdown();
}
}
第四步:自定义线程回调方法类(一般定义在父级模块),这里执行主要的业务代码
package cn.springcloud.book.common.test;
import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 线程回调方法
*/
public class ObjectCallable implements Callable
{
private static Logger lOG = LoggerFactory.getLogger(ObjectCallable.class);
private Object object;
//private ObjectService objectService;
/**
* 这个方法一定会执行
*/
private void init()
{
//执行初始化相关bean对象(Object,Service)
//objectService = SpringContextUtil.getBean(ObjectService.class);
}
public ObjectCallable(Object object)
{
this.object = object;
init();
}
@Override
public Object call() throws Exception
{
//执行数据新增或者更新的业务
//操作Object对象数据
return null;
}
}
好了,到这一步,基本的业务类都已经准备了,就差最后开启数据同步新增或更新操作了。
最后一步,在原数据对象serviceImpl层的新增或更新操作的方法中,发布事件,这样一整套流程就搭建好了,事务是也是同样有效的。
引入事件发布者对象:
发布事件:
//list为对象集合
applicationContext.publishEvent(new MtPlanMainSyncEvent("remind", list));