Java实现双保险线程的示例代码
作者:IT_熊 发布时间:2023-09-21 07:59:46
标签: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);
}
}
来源:https://blog.csdn.net/servermanage/article/details/103640228


猜你喜欢
- 🚀 ChatGPT是最近很热门的AI智能聊天机器人🚀 本文使用SpringBoot+OpenAI的官方API接口,自己实现一个可以返回对话数
- 网上有很多类似的文章,大多数还是继承listview来实现(主要是listview.addHeaderView()和listview.add
- 本文实例为大家分享了Android文件下载功能的具体代码,供大家参考,具体内容如下1.普通单线程下载文件:直接使用URLConnection
- Oracle官网是这样介绍默认方法的,使用默认方法,可以达到往接口里面增加新的功能,而且保持与老版本代码兼容,也就是原来的实现类可以不需要被
- 目录一、基本使用二、常用的 APIImageLoaderImageRequestDisposable图片变换三、功能拓展Intercepto
- 导入maven依赖<!-- https://mvnrepository.com/artifact/com.fasterxml.jack
- 假设我们有一个类:Productpublic class Product{ public string
- 它可以做什么?它做的事情当然是生成新类或修改原始的类,比如你遇到这样的情况下就可以使用:反射好慢,曾见过一个大厂大量是Gson,由于Gson
- 类的定义面向对象的程序设计中,类可以看作是我们自定义的数据类型,那么,如何能更加优美,更加高效地定义它就显得尤为重要。类中的成员有很多,每一
- java8的stream取max public static void main(String[] args) { &
- 最近在玩3g体育门户客户端的时候,看到这样个效果: 轻触赛事图标,会有一个图标变大浮出的效果.,蛮有意思的.于是就把仿照它做了一
- 闹钟闹不醒的可以自己去调整下,这个最是最基本的MainActivitypublic class MainActivity extends A
- 就我们所知道的,java中有子类和父类,子类由于继承父类而形成,那么父类还有没有父类呢?答案是有了,父类的父类就是object类,一切父类都
- 本文实例为大家分享了C#基于Socket实现多人聊天功能的具体代码,供大家参考,具体内容如下服务器服务器负责接受所有客户端发来的消息,和将接
- 在SpringBoot中,当需要获取到配置文件数据时,除了可以用Spring自带的@Value注解外,SpringBoot提供了一种更加方便
- .NET包含一个特殊的Object类,可以接受任意的数据类型的值,当所传递或所赋值的类型不是一个特定的数据类型时,object类就提供了一种
- 前言介绍了几篇 Hero 动画,我们来一个 Hero 动画应用案例。在一些应用中,列表的元素和详情的
- Shiro介绍Shiro是一款安全框架,主要的三个类Subject、SecurityManager、RealmSubject:表示当前用户S
- main.xml:<?xml version="1.0" encoding="utf-8"?&
- 一、整合原理activiti的配置文件本身就是一个spring的配置文件,但默认情况下只讲ProcessEngineConfiguratio