1. 程式人生 > 程式設計 >Java實現雙保險執行緒的示例程式碼

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);
  }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。