本文使用:
Timer:這是java自帶的java.util.Timer類,這個類允許你調度一個java.util.TimerTask任務。使用這種方式可以讓你的程序按照某一個頻度執行,
但不能在指定時間運行。一般用的較少。
類似於quartz任務調度: demo地址 lsr-core-base模塊中
直接上代碼:
線程基類:
package cn.lsr.core.thread; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.Timestamp; import java.util.Timer; import java.util.TimerTask; /** * @Description: 輪詢線程基類 * @Package: lsr-microservice * @author: Hacker_lsr@126.com **/ public abstract class AbstractPollThread { private static final Logger log = LoggerFactory.getLogger(AbstractPollThread.class); private long delay = 60; // 延期時間(第一次執行時間-調用時間) private long timeInterval = 60; //時間間隔(s) private Timer timer; private Timestamp lastProcess = null; //上次執行的時間 private boolean isTimerStart = false; //定時器是否啟動 private boolean isOnProcessing = false; //是否在執行處理 private final String threadName; //線程名稱 private final String threadId; //線程標識 private final String longname; //中文名稱 private long processCount = 0; //執行次數 private long processTime = 0; //已運行時間 private long errorProcessCount = 0; //執行失敗的次數 public AbstractPollThread(String threadId, String threadName, String longname, Long delay, Long timeInterval) { this.threadId = threadId; this.threadName = threadName; this.longname = longname; if (timeInterval != null && timeInterval > 0) this.timeInterval = timeInterval; if (delay != null) this.delay = delay; PollThreadManager.get().register(threadName, this); } /** * 線程啟動時回調方法。 */ public void init() { } /** * 輪詢間隔回調方法。 */ public abstract void process(); /** * 啟動方法 */ public void startup() { this.timer = new Timer( "lsr-timer-" + this.threadName, false); try { this.timer.schedule(new TimerTask() { boolean initialized = false; @Override public void run() { // 異步線程資源清理 //清理完上下文數據,在打log4j標記 log.info("--------------------輪訓線程[" + AbstractPollThread.this.threadName + "]開始調度--------------------"); // 2015.4.20 每個線程開始受理請求時對數據庫連接進行檢查,若不可用則重連一次 long start = System.currentTimeMillis(); try { AbstractPollThread.this.isOnProcessing = true; AbstractPollThread.this.lastProcess = new Timestamp(System.currentTimeMillis()); AbstractPollThread.this.process(); AbstractPollThread.this.isOnProcessing = false; } catch (Throwable t) { log.error("輪詢線程出現異常", t); AbstractPollThread.this.errorProcessCount++; } finally { AbstractPollThread.this.processCount++; AbstractPollThread.this.processTime = AbstractPollThread.this.processTime + System.currentTimeMillis() - start; log.info("--------------------輪訓線程[" + AbstractPollThread.this.threadName + "]調度結束. [" + (System.currentTimeMillis() - start) + "]--------------------"); // 異步線程資源清理 } } }, this.delay * 1000, this.timeInterval * 1000); this.isTimerStart = true; } catch (Exception e) { this.isTimerStart = false; log.error("輪詢線程設置定時器失敗,", e); throw new RuntimeException("輪詢線程設置定時器失敗", e); } } public void shutdown() { try { if (this.timer != null) this.timer.cancel(); this.isTimerStart = false; } catch (Exception e) { this.isTimerStart = false; log.error("關閉輪詢線程中的定時器失敗", e); throw new RuntimeException("關閉輪詢線程中的定時器失敗", e); } } public String getThreadName() { return this.threadName; } public String getLongname() { return this.longname; } public long getProcessCount() { return this.processCount; } public long getProcessTime() { return this.processTime; } public long getErrorProcessCount() { return this.errorProcessCount; } public void setTimeInterval(long timeInterval) { this.timeInterval = timeInterval; } public long getTimeInterval() { return this.timeInterval; } public boolean isTimerStart() { return this.isTimerStart; } public boolean isOnProcessing() { return this.isOnProcessing; } public String getLastProcessTime() { return this.lastProcess == null ? null : this.lastProcess.toString(); } public void resetCountInfo() { this.processCount = 0; this.processTime = 0; this.errorProcessCount = 0; this.lastProcess = null; } }
輪詢線程配置類:
package cn.lsr.core.thread; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; /** * @Description: 輪詢線程配置 * @Package: lsr-microservice * @author: Hacker_lsr@126.com **/ public class PollThreadConfig { /** * 輪詢線程ID */ private String threadId; /** * 輪詢線程名稱 */ private String threadName; /** * 間隔時間 */ private Long timeInterval; /** * 輪詢線程首次延遲時間 */ private Long delay; // get set 省略 }
線程管理器:
package cn.lsr.core.thread; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @Description: 線程管理器 * @Package: lsr-microservice * @author: Hacker_lsr@126.com **/ public class PollThreadManager { private final static Map<String, AbstractPollThread> pollThreadMap = new ConcurrentHashMap<String, AbstractPollThread>(); private final static PollThreadManager instance = new PollThreadManager(); public static PollThreadManager get() { return instance; } public void register(String threadName, AbstractPollThread pollThread) { pollThreadMap.put(threadName, pollThread); } public AbstractPollThread getPollThread(String threadName) { return pollThreadMap.get(threadName); } public Map<String, AbstractPollThread> getPollThreads() { return pollThreadMap; } }
測試線程(可擴展):
package cn.lsr.core.thread; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.Timestamp; /** * @Description: 測試輪詢線程 * @Package: lsr-microservice * @author: Hacker_lsr@126.com **/ public class TestServerPollThread extends AbstractPollThread{ private static final Logger log = LoggerFactory.getLogger(TestServerPollThread.class); /** * 插件 - OnlineServerManagerPlugin -啟動的時候初始化線程 * @param threadId 輪詢線程ID * @param threadName 輪詢線程名稱 * @param longname 中文名稱 * @param delay 輪詢線程首次延遲時間 * @param timeInterval 時間間隔 */ public TestServerPollThread(String threadId, String threadName, String longname, Long delay, Long timeInterval) { super(threadId, threadName, longname, delay, timeInterval); } /** * 輪詢間隔回調方法 */ @Override public void process() { log.info("刷新時間為:{}", new Timestamp(System.currentTimeMillis())); //邏輯 } }
使用:
//注入: private TestServerPollThread testServerPollThread; // 封裝的工具類,獲取的ioc的線程配置 PollThreadConfig pollThreadConfig = SpringUtil.getBean(PollThreadConfig.class); testServerPollThread = new TestServerPollThread(pollThreadConfig.getThreadId(),pollThreadConfig.getThreadName(),pollThreadConfig.getThreadName(),pollThreadConfig.getDelay(),pollThreadConfig.getTimeInterval()); //調用方法 testServerPollThread.startup();
application.properties:
##################################### 輪詢線程 #######################################
#開關 lsr.poll.thread.enabled=true
#線程id lsr.poll.thread.threadId=LSRThread
#線程中文名 lsr.poll.thread.threadName=輪詢線程
#間隔時間 lsr.poll.thread.timeInterval=60
#加載延遲時間 lsr.poll.thread.delay=60