Java实现双保险线程的示例代码

作者:IT_熊 时间:2023-09-21 07:59:46 

双保险线程,每次启动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);
 }
}

来源:https://blog.csdn.net/servermanage/article/details/103640228

标签:Java,双保险,线程
0
投稿

猜你喜欢

  • 如何利用反射构建元数据查看器

    2021-05-27 00:11:05
  • 如何在springboot中实现页面的国际化

    2021-08-13 03:33:07
  • Mybatis中Mapper映射文件使用详解

    2023-02-13 17:57:07
  • 详谈springboot过滤器和拦截器的实现及区别

    2022-07-22 04:44:24
  • JDBC SQL语法

    2022-03-09 02:32:10
  • Logback配置文件这么写,还说你不会整理日志?

    2022-10-30 10:23:09
  • Java源码解析之ClassLoader

    2022-06-14 06:07:47
  • SpringBoot + SpringSecurity 短信验证码登录功能实现

    2022-10-16 10:26:25
  • 浅谈利用Session防止表单重复提交

    2022-02-08 00:45:42
  • c#分页读取GB文本文件实例

    2021-09-13 10:18:39
  • C++ 中二分查找递归非递归实现并分析

    2023-06-19 06:51:31
  • Java常问面试内容--数组、声明、初始化、冒泡、多维数组、稀疏数组

    2021-08-20 02:05:52
  • C#异步编程由浅入深(二)之Async/Await的使用

    2022-10-14 16:45:20
  • Java 详解Collection集合之ArrayList和HashSet

    2021-09-10 06:27:02
  • Android实现选项菜单子菜单

    2023-06-14 16:06:26
  • Android在linux下刷机教程

    2023-09-03 17:21:04
  • Java spring的三种注入方式详解流程

    2021-07-02 12:25:47
  • IDEA+Maven搭建Spring环境的详细教程

    2023-11-25 07:50:34
  • android 通知Notification详解及实例代码

    2023-06-26 12:11:42
  • Springboot中如何使用Jackson

    2021-07-29 03:27:34
  • asp之家 软件编程 m.aspxhome.com