Java实现双保险线程的示例代码
双保险线程,每次启动2个相同的线程,互相检测,避免线程死锁造成影响。
两个线程都运行,但只有一个线程执行业务,但都会检测对方的时间戳 如果时间戳超过休眠时间3倍没有更新的话,则重新启动对方线程。
例子:
一般工作线程由自己实现,继承DoubleInsuredThead,在run2()方法里实现具体需求,和一般线程的run()方法不同,run2()里不用处理循环和休眠 检测线程已经由CheckThread实现,可以直接使用,如:启动用户检测线程。
public static void startMonitor() { System.out.println("启动用户会话检测线程"); UserMonitor worker = new UserMonitor("WT-UserMonitor"); CheckThread checker = new CheckThread("WT-UserMonitorCheck",userMonitorIntevalTime); DoubleInsuredThead.startDoubleInsuredThead(worker, checker); }
完整代码:
package com.yx.demo.thread; /** * DoubleInsuredThead * 双保险线程,每次启动2个相同的线程,互相检测,避免线程死锁造成影响。 * <p> * 两个线程都运行,但只有一个线程执行业务,但都会检测对方的时间戳 如果时间戳超过休眠时间3倍没有更新的话,则重新启动对方线程 * <p> * 代码例子: * 一般工作线程由自己实现,继承DoubleInsuredThead,在run2()方法里实现具体需求,和一般线程的run()方法不同,run2() * 里不用处理循环和休眠 检测线程已经由CheckThread实现,可以直接使用 * * <pre> * 启动用户检测线程 * public static void startMonitor() { * System.out.println("启动用户会话检测线程"); * UserMonitor worker = new UserMonitor("XX-UserMonitor"); * CheckThread checker = new CheckThread("XX-UserMonitorCheck",userMonitorIntevalTime); * DoubleInsuredThead.startDoubleInsuredThead(worker, checker); * } * </pre> * * @author yx * @date 2019/12/21 0:36 */ public abstract class DoubleInsuredThead extends Thread { /** * 默认线程休眠时间为1000毫秒 */ public static final long DEFAULT_SLEEP_TIME = 1000; /** * 是否运行本线程 */ private boolean running = true; /** * 线程时间戳,每次run的时候更新 */ private long timeStamp = System.currentTimeMillis(); /** * 互相检测的另外一个线程 */ DoubleInsuredThead another; public DoubleInsuredThead(String name) { super(name); } /** * 子线程的执行业务的方法,相当于Runnable.run()方法 */ public abstract void run2(); /** * 获得实例,重启线程的时候用 * * @return */ public abstract DoubleInsuredThead newInstance(); /** * 启动工作线程,使用默认检测线程 * * @param workerThread */ public static void startDoubleInsuredThead(DoubleInsuredThead workerThread) { CheckThread checkerThread = new CheckThread(workerThread.getName() + "-checker", workerThread.getSleepTime()); workerThread.another = checkerThread; checkerThread.another = workerThread; workerThread.start(); checkerThread.start(); } /** * 自定义检测线程的方式启动工作线程,建议使用startDoubleInsuredThead(DoubleInsuredThead workerThread) * * @param worker 工作线程 * @param checker 检测线程 * @deprecated */ public static void startDoubleInsuredThead(DoubleInsuredThead worker, DoubleInsuredThead checker) { worker.another = checker; checker.another = worker; worker.start(); checker.start(); } /** * 重启线程 */ public void restart() { System.out.println("线程\"" + getName() + "\"重新启动了"); // 停止当前线程 running = false; // 启动新线程 DoubleInsuredThead t = newInstance(); t.setTimeStamp(System.currentTimeMillis()); another.another = t; t.another = another; t.start(); } @Override public void run() { while (running) { // 执行子类线程的业务 run2(); checkAnother(); setTimeStamp(System.currentTimeMillis()); try { Thread.sleep(getSleepTime()); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("线程休眠出错:" + e.getMessage()); } } } /** * 获得线程休眠的时间,单位毫秒 * * @return */ public long getSleepTime() { return DEFAULT_SLEEP_TIME; } /** * 对另外一个线程进行检测 */ private void checkAnother() { if (another.isTimeout()) { another.restart(); } } /** * 是否更新时间戳超时 * * @return */ private boolean isTimeout() { System.out.println("timeStamp = " + getTimeStamp()); return System.currentTimeMillis() - getTimeStamp() > getSleepTime() * 3; } /** * @param timeStamp the timeStamp to set */ public void setTimeStamp(long timeStamp) { this.timeStamp = timeStamp; } /** * @return the timeStamp */ public long getTimeStamp() { return timeStamp; } }
检测线程:
package com.yx.demo.thread; /** * CheckThread * 双保险线程里专门用来检测的线程 * * @author yx * @date 2019/12/21 0:38 */ public class CheckThread extends DoubleInsuredThead { /** * 检测休眠时间,默认1秒 */ private long checkIntevalTime = 1000; public CheckThread(String name, long checkTime) { super(name); this.checkIntevalTime = checkTime; } @Override public DoubleInsuredThead newInstance() { return new CheckThread(getName(), checkIntevalTime); } @Override public void run2() { // 只打印信息 System.out.println("线程" + getName() + "完成了工作"); } @Override public long getSleepTime() { return checkIntevalTime; } /** * 测试代码 * * @param args */ public static void main(String[] args) { CheckThread worker = new CheckThread("worker", 3000); DoubleInsuredThead.startDoubleInsuredThead(worker); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
上一篇:如何基于SpringBoot部署外部Tomcat过程解析
栏 目:Java
本文标题:Java实现双保险线程的示例代码
本文地址:https://www.xiuzhanwang.com/a1/Java/8917.html
您可能感兴趣的文章
- 01-10Java实现动态模拟时钟
- 01-10利用Java实现复制Excel工作表功能
- 01-10JavaWeb实现邮件发送功能
- 01-10java基于poi导出excel透视表代码实例
- 01-10Java实现动态数字时钟
- 01-10基于Java验证jwt token代码实例
- 01-10java实现液晶数字字体显示当前时间
- 01-10浅谈Java中真的只有值传递么
- 01-10Java动态显示当前日期和时间
- 01-10如何解决线程太多导致java socket连接池出现的问题
阅读排行
本栏相关
- 01-10Java实现动态模拟时钟
- 01-10Springboot中@Value的使用详解
- 01-10JavaWeb实现邮件发送功能
- 01-10利用Java实现复制Excel工作表功能
- 01-10Java实现动态数字时钟
- 01-10java基于poi导出excel透视表代码实例
- 01-10java实现液晶数字字体显示当前时间
- 01-10基于Java验证jwt token代码实例
- 01-10Java动态显示当前日期和时间
- 01-10浅谈Java中真的只有值传递么
随机阅读
- 08-05DEDE织梦data目录下的sessions文件夹有什
- 01-11ajax实现页面的局部加载
- 01-10delphi制作wav文件的方法
- 01-10SublimeText编译C开发环境设置
- 01-10C#中split用法实例总结
- 01-11Mac OSX 打开原生自带读写NTFS功能(图文
- 08-05dedecms(织梦)副栏目数量限制代码修改
- 04-02jquery与jsp,用jquery
- 01-10使用C语言求解扑克牌的顺子及n个骰子
- 08-05织梦dedecms什么时候用栏目交叉功能?