日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前言:

我們日常總會碰到這樣的需求:

  • 把這個任務放到另外一個線程執行。
  • 我需要周期性執行任務的線程。那我們通常都是怎么解決這個問題呢?
  • 對于問題1,最簡單的做法就是new thread,然后結束了。但在生產環境中,你常常會困擾,我這個線程到底執行沒,或者是否正在執行。任務報錯了日志在哪里呢?
  • 對于問題2,我們可能會選擇定時器,ScheduledExecutor,但如果你想追蹤你的線程運行情況,或者捕獲異常,這都沒法隨心所欲

針對上面常見的兩個問題,我自己封裝了一個標準的后臺線程模型

一、完整代碼實現

/**

* DefaultThread 后臺標準線程

*/

public final class DefaultThread extends Thread {

/** log */

private static final Logger log = InternalLoggerFactory.getLogger(DefaultThread.class);

/** 標準后臺線程循環間隔時間 - 1分鐘 */

public static final long DEFAULT_INTERVAL = 60 * 1000;

/** 標準后臺線程循環最小間隔 - 300ms */

public static final long MIN_INTERVAL = 300;

/** 默認日志輸出級別 -- debug */

public static final LogLevel DEFAULT_LEVEL = LogLevel.DEBUG;

private String name;

private Runnable runnable;

private boolean runOnce;

private volatile boolean stop;

private volatile long interval;

private volatile LogLevel level = DEFAULT_LEVEL;

/**

* 構造函數

* <p>將構造一個標準后臺線程,每分鐘運行1次

* @param name

* @param runnable

*/

public DefaultThread(String name, Runnable runnable) {

super(name);

this.name = name;

this.runnable = runnable;

this.runOnce = false;

this.stop = false;

this.interval = DEFAULT_INTERVAL;

}

/**

* 構造函數

* <p>將構造一個標準后臺線程

* @param name

* @param runnable

* @param runOnce

* @param interval

*/

public DefaultThread(String name, Runnable runnable, boolean runOnce) {

super(name);

this.name = name;

this.runnable = runnable;

this.runOnce = runOnce;

this.stop = false;

this.interval = DEFAULT_INTERVAL;

}

/**

* 構造函數

* <p>將構造一個標準后臺線程,指定間隔運行一次(不能小于最小間隔時間{@link #MIN_INTERVAL}})

* @param name

* @param runnable

* @param runOnce

* @param interval

*/

public DefaultThread(String name, Runnable runnable, long interval) {

super(name);

this.name = name;

this.runnable = runnable;

this.runOnce = false;

this.stop = false;

this.interval = Math.max(MIN_INTERVAL, interval);

}

@Override

public void start() {

super.start();

}

public void stop() {

try {

this.interrupt();

} catch (Exception e) {

// Ignore

}

this.stop = true;

}

/**

* 獲得線程名稱

*/

public String getThreadName() {

return this.name;

}

/**

* 設置日志隔離級別

*/

public void setLogLevel(LogLevel level) {

this.level = level;

}

/**

* 執行任務

* @see JAVA.lang.Thread#run()

*/

public final void run() {

if (runOnce) {

runOnce();

return;

}

while (!stop) {

runOnce();

try {

sleep(interval);

} catch (InterruptedException e) {

// Ignore this Exception

}

}

}

/**

* 執行一次

*/

private void runOnce() {

long startTime = 0;

if (log.isLogEnabled(level)) {

startTime = System.currentTimeMillis();

}

try {

runnable.run();

} catch (Throwable t) {

log.error("thread run error [name:{}, runOnce:{}]", t, name, runOnce);

}

if (log.isLogEnabled(level)) {

log.log(level, "{}#{}", (System.currentTimeMillis() - startTime));

}

}

二、代碼解讀

線程名稱變成強制性

創建標準線程,必須指定線程名稱,這是為了方便在jstack等工具中追蹤

可以定義為周期性執行

周期性執行中做了預防措施,防止定義過小的周期,引起死循環,占用過高CPU

每次執行可追蹤

每次執行,如果在debug模式下將記錄執行時間,對執行異常也進行捕獲打印日志,方便追蹤bug

線程可停止

Java提供的線程并沒有提供停止方法,該封裝中通過一個標志位實現該功能,能夠中斷線程

結語:

線程雖然簡單,但在實際使用中也要注意規范,每個線程都是隨意new,隨意使用的話會造成后續維護,bug追蹤方便極大的困難。建議項目中的線程都遵從同一個標準。本文僅是個人實踐拙見,歡迎拍磚!

分享到:
標簽:Java
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定