项目运用rabbitMq 实现的分布式架构,每台机器既是生成者也是消费者,改项目依赖于外部调度服务,mq的consumer listener引用其他组的jar包(实现对外部资源的调用),消息消费是单线程的,在此调用jar包操作业务或者是个人代码写的有问题,可能导致线程死锁,或者其他代码问题(http请求未设置超时),导致消息消费被卡住,最终消息堆积。导致正常业务垮掉。既然consumer没配置消息的超时时间,java支持多线程,那么可以用来完美解决,worker线程执行任务,protect线程监听worker线程判断执行时间,(其实这两个线程都是在同时互相监听,各自执行完毕stop未执行完成的线程)不啰嗦直接上代码
BaseThreadUtil类 worker 线程和protect线程集成该抽象类
/** * Created by liweigao on 2017/4/25. */ public abstract class BaseThreadUtil extends Thread { public abstract void execute();//抽象方法需要子类实现 private String threadName = ""; //在父类重写run方法,在子类只要重写execute方法就可以了 @Override public void run() { super.run(); execute(); } //在需要回调数据的地方(两个子类需要),声明一个接口 public static interface Callback { public void complete(); } //2.创建接口对象 public Callback callback; public String getThreadName() { return threadName; } public void setThreadName(String threadName) { this.threadName = threadName; } }
worker 线程类 执行主要业务线程。
/** * Created by liweigao on 2017/4/25. */ public class WorkerThread extends BaseThreadUtil { private Logger logger = LoggerFactory.getLogger(WorkerThread.class); private Runnable runnable; public WorkerThread(Runnable runnable, String threadName) { this.runnable = runnable; if (threadName != null && !"".equals(threadName)) { super.setThreadName(threadName); } else { super.setThreadName("worker thread"); } } @Override public void execute() { StopWatch stopWatch=new StopWatch(); stopWatch.start(); if (runnable != null) { runnable.run(); } stopWatch.stop(); // System.out.println("线程:" + super.getThreadName() + "执行完毕,开始执行回调……"); logger.debug("线程:" + super.getThreadName() + "执行完毕,开始执行回调……耗时:"+stopWatch.getTotalTimeMillis() +"ms"); //任务执行完毕 执行回调 callback.complete(); } }
protect 线程类。
/** * Created by liweigao on 2017/4/25. */ public class ProtectThread extends BaseThreadUtil { private Logger logger = LoggerFactory.getLogger(ProtectThread.class); private Integer timeout = 6000; public ProtectThread(Integer timeout, String threadName) { this.timeout = timeout; if (threadName != null && !"".equals(threadName)) { super.setThreadName(threadName); } else { super.setThreadName("protect thread"); } } @Override public void execute() { StopWatch stopWatch = new StopWatch(); stopWatch.start(); try { Thread.sleep(timeout); } catch (InterruptedException e) { logger.error(e.getMessage(), e); } stopWatch.stop(); // System.out.println("线程:" + super.getThreadName() + "执行完毕,开始执行回调……"); logger.debug( "线程:" + super.getThreadName() + "执行完毕,开始执行回调……耗时:" + stopWatch.getTotalTimeMillis() + "ms"); //线程任务执行完毕 执行回调 callback.complete(); } }
baseStopUtil 类 也可以叫回调类,处理未完成线程。
/** * Created by liweigao on 2017/4/25. */ public class BaseStopUtil implements Callback { private Logger logger = LoggerFactory.getLogger(BaseStopUtil.class); BaseThreadUtil baseCallBackUtil; // 获取对象 public BaseStopUtil(BaseThreadUtil baseCallBackUtil) { this.baseCallBackUtil = baseCallBackUtil; } @Override public void complete() { // System.out.println("线程:" + baseCallBackUtil.getThreadName() + "被停掉……"); logger.debug("线程:" + baseCallBackUtil.getThreadName() + "被停掉……"); if (baseCallBackUtil.isAlive()) { baseCallBackUtil.stop(); } } }
ListenThreadConsumer 封装对外调用方法,启动两个线程,配置超时时间。
/** * Created by liweigao on 2017/4/25. */ public class ListenThreadConsumer { /** * 过期时间 */ private Integer timeout; /** * 任务 */ private Runnable runnable; /** * 检测间隔时间 默认1000 */ // private Integer spacetime; public ListenThreadConsumer(Integer timeout, Runnable runnable) { this.timeout = timeout; this.runnable = runnable; } public void execute() { ProtectThread protectThread = new ProtectThread(timeout, ""); WorkerThread workerThread = new WorkerThread(runnable, ""); protectThread.callback = new BaseStopUtil(workerThread); workerThread.callback = new BaseStopUtil(protectThread); protectThread.start(); workerThread.start(); } }
那么就可以很简单的运用到自己的程序中了。main方法测试。
public static void main(String[] args) { ListenThreadConsumer listenThreadConsumer = new ListenThreadConsumer(100, new Runnable() { @Override public void run() { System.out.println("这是我的测试……………………"); } }); //执行任务以及监控 listenThreadConsumer.execute(); }
打印日志: 这是我的测试…………………… 2017-04-28 18:56:50.916 [Thread-1] DEBUG c.w.s.c.util.thread.WorkerThread-[34] - 线程:worker thread执行完毕,开始执行回调……耗时:1ms 2017-04-28 18:56:50.922 [Thread-1] DEBUG c.w.s.c.util.thread.BaseStopUtil-[23] - 线程:protect thread被停掉…… 以上完毕,可直接copy复用。以上信息欢迎大神吐槽,欢迎提建议。互相监控,其中哪一个线程有问题,都会被停掉。