Java實現(xiàn)雙保險線程的示例代碼
雙保險線程,每次啟動2個相同的線程,互相檢測,避免線程死鎖造成影響。
兩個線程都運行,但只有一個線程執(zhí)行業(yè)務(wù),但都會檢測對方的時間戳 如果時間戳超過休眠時間3倍沒有更新的話,則重新啟動對方線程。
例子:
一般工作線程由自己實現(xiàn),繼承DoubleInsuredThead,在run2()方法里實現(xiàn)具體需求,和一般線程的run()方法不同,run2()里不用處理循環(huán)和休眠 檢測線程已經(jīng)由CheckThread實現(xiàn),可以直接使用,如:啟動用戶檢測線程。
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> * 兩個線程都運行,但只有一個線程執(zhí)行業(yè)務(wù),但都會檢測對方的時間戳 如果時間戳超過休眠時間3倍沒有更新的話,則重新啟動對方線程 * <p> * 代碼例子: * 一般工作線程由自己實現(xiàn),繼承DoubleInsuredThead,在run2()方法里實現(xiàn)具體需求,和一般線程的run()方法不同,run2() * 里不用處理循環(huán)和休眠 檢測線程已經(jīng)由CheckThread實現(xiàn),可以直接使用 * * <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 { /** * 默認(rèn)線程休眠時間為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); } /** * 子線程的執(zhí)行業(yè)務(wù)的方法,相當(dāng)于Runnable.run()方法 */ public abstract void run2(); /** * 獲得實例,重啟線程的時候用 * * @return */ public abstract DoubleInsuredThead newInstance(); /** * 啟動工作線程,使用默認(rèn)檢測線程 * * @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() + "\"重新啟動了"); // 停止當(dāng)前線程 running = false; // 啟動新線程 DoubleInsuredThead t = newInstance(); t.setTimeStamp(System.currentTimeMillis()); another.another = t; t.another = another; t.start(); } @Override public void run() { while (running) { // 執(zhí)行子類線程的業(yè)務(wù) 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 { /** * 檢測休眠時間,默認(rèn)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); } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:如何基于SpringBoot部署外部Tomcat過程解析
欄 目:Java
本文標(biāo)題:Java實現(xiàn)雙保險線程的示例代碼
本文地址:http://mengdiqiu.com.cn/a1/Java/8917.html
您可能感興趣的文章
- 01-10Java實現(xiàn)動態(tài)模擬時鐘
- 01-10利用Java實現(xiàn)復(fù)制Excel工作表功能
- 01-10JavaWeb實現(xiàn)郵件發(fā)送功能
- 01-10java基于poi導(dǎo)出excel透視表代碼實例
- 01-10Java實現(xiàn)動態(tài)數(shù)字時鐘
- 01-10基于Java驗證jwt token代碼實例
- 01-10java實現(xiàn)液晶數(shù)字字體顯示當(dāng)前時間
- 01-10淺談Java中真的只有值傳遞么
- 01-10Java動態(tài)顯示當(dāng)前日期和時間
- 01-10如何解決線程太多導(dǎo)致java socket連接池出現(xiàn)的問題


閱讀排行
本欄相關(guān)
- 01-10Java實現(xiàn)動態(tài)模擬時鐘
- 01-10Springboot中@Value的使用詳解
- 01-10JavaWeb實現(xiàn)郵件發(fā)送功能
- 01-10利用Java實現(xiàn)復(fù)制Excel工作表功能
- 01-10Java實現(xiàn)動態(tài)數(shù)字時鐘
- 01-10java基于poi導(dǎo)出excel透視表代碼實例
- 01-10java實現(xiàn)液晶數(shù)字字體顯示當(dāng)前時間
- 01-10基于Java驗證jwt token代碼實例
- 01-10Java動態(tài)顯示當(dāng)前日期和時間
- 01-10淺談Java中真的只有值傳遞么
隨機閱讀
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-10delphi制作wav文件的方法
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實例總結(jié)
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 08-05織夢dedecms什么時候用欄目交叉功能?