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

网友投稿 230 2022-12-18


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个相同的线程,互相检测,避免线程死锁造成影响。

*

* 两个线程都运行,但只有一个线程执行业务,但都会检测对方的时间戳 如果时间戳超过休眠时间3倍没有更新的话,则重新启动对方线程

*

* 代码例子:

* 一般工作线程由自己实现,继承DoubleInsuredThead,在run2()方法里实现具体需求,和一般线程的run()方法不同,run2()

* 里不用处理循环和休眠 检测线程已经由CheckThread实现,可以直接使用

*

*

* 启动用户检测线程

* public static void startMonitor() {

* http://System.out.println("启动用户会话检测线程");

* UserMonitor worker = new UserMonitor("XX-UserMonitor");

* CheckThread checker = new CheckThread("XX-UserMonitorCheck",userMonitorIntevalTime);

* DoubleInsuredThead.startDoubleInsuredThead(worker, checker);

* }

*

*

* @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

*/

publhttp://ic 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 Chhttp://eckThread(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);

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SPRING BOOT启动命令参数及源码详析
下一篇:SpringBoot使用RabbitMQ延时队列(小白必备)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~