java自定義線程模型處理方法分享
看過我之前文章的園友可能知道我是做游戲開發(fā),我的很多思路和出發(fā)點是按照游戲思路來處理的,所以和web的話可能會有沖突,不相符合。
來說說為啥我要自定義線程模型呢?
按照我做的mmorpg或者mmoarpg游戲劃分,線程被劃分為,主線程,全局同步線程,聊天線程,組隊線程,地圖線程,以及地圖消息分發(fā)派送線程等;
一些列,都需要根據(jù)我的劃分,以及數(shù)據(jù)流向做控制。
游戲服務(wù)器,主要要做的事情,肯定是接受玩家的 命令請求 -> 相應(yīng)的操作 -> 返回結(jié)果;
在服務(wù)器端所有的消息都會注冊到消息管理器里,然后消息在注冊的時候會指定線程模型,
如果消息需要提交到玩家所在地圖線程進行處理的話注冊消息的時候就要把線程模型用(地圖消息分發(fā)派送線程);
下面我們先來分析線程模型;
在看線程模型代碼之前我先看看我的任務(wù)模型
package net.sz.engine.thread; import java.io.Serializable; import org.apache.log4j.Logger; import net.sz.engine.structs.ObjectAttribute; import net.sz.engine.structs.ObjectGlobal; /** * 任務(wù)模型 * * <br> * author 失足程序員<br> * mail 492794628@qq.com<br> * phone 13882122019<br> */ public abstract class TaskEvent implements Serializable, Cloneable { private static final Logger log = Logger.getLogger(TaskEvent.class); private static final long serialVersionUID = 4196020659994845804L; //運行時數(shù)據(jù) private transient final ObjectAttribute runOther = new ObjectAttribute; //任務(wù)創(chuàng)建的時間 protected long createTime; //任務(wù)的唯一id protected long taskId; //取消的任務(wù) protected boolean cancel = false; public TaskEvent { this.runOther.put("submitTime", System.currentTimeMillis); createTime = System.currentTimeMillis; cancel = false; taskId = ObjectGlobal.getUUID; } public long getCreateTime { return createTime; } public void setCreateTime(long createTime) { this.createTime = createTime; } public long getSubmitTime { return this.runOther.getlongValue("submitTime"); } public ObjectAttribute getRunOther { return runOther; } public boolean isCancel { return cancel; } public void setCancel(boolean cancel) { this.cancel = cancel; } public abstract void run; @Override public Object clone throws CloneNotSupportedException { return super.clone; //To change body of generated methods, choose Tools | Templates. } }
package net.sz.engine.thread; /** * 定時器執(zhí)行器 * * <br> * author 失足程序員<br> * mail 492794628@qq.com<br> * phone 13882122019<br> */ public abstract class TimerTaskEvent extends TaskEvent { private static final long serialVersionUID = -8331296295264699207L; /** * 開始執(zhí)行的時間 */ protected long startTime; /** * 是否一開始執(zhí)行一次 */ protected boolean startAction; /** * 結(jié)束時間 */ protected long endTime; /** * 執(zhí)行次數(shù) */ protected int actionCount; /** * 間隔執(zhí)行時間 */ protected int intervalTime; /** * * @param startTime 指定開始時間 * @param isStartAction 是否一開始就執(zhí)行一次 * @param endTime 指定結(jié)束時間 * @param actionCount 指定執(zhí)行次數(shù) * @param intervalTime 指定間隔時間 */ public TimerTaskEvent(long startTime, boolean isStartAction, long endTime, int actionCount, int intervalTime) { super; this.startTime = startTime; this.startAction = isStartAction; this.endTime = endTime; this.actionCount = actionCount; this.intervalTime = intervalTime; } /** * 指定任務(wù)的開始執(zhí)行時間 * * @param startTime 指定開始時間 * @param isStartAction 是否一開始就執(zhí)行一次 * @param actionCount 指定執(zhí)行次數(shù) * @param intervalTime 指定間隔時間 */ public TimerTaskEvent(long startTime, boolean isStartAction, int actionCount, int intervalTime) { this(startTime, isStartAction, 0, actionCount, intervalTime); } /** * 指定結(jié)束時間已結(jié)束時間為準(zhǔn),執(zhí)行次數(shù)不一定夠 * * @param isStartAction 是否一開始就執(zhí)行一次 * @param endTime 指定結(jié)束時間 * @param actionCount 指定執(zhí)行次數(shù) * @param intervalTime 指定間隔時間 * */ public TimerTaskEvent(boolean isStartAction, long endTime, int actionCount, int intervalTime) { this(0, isStartAction, endTime, actionCount, intervalTime); } /** * 指定開始時間,和結(jié)束時間 * * @param startTime 指定開始時間 * @param endTime 指定結(jié)束時間 * @param intervalTime 指定間隔時間 */ public TimerTaskEvent(long startTime, long endTime, int intervalTime) { this(startTime, false, endTime, -1, intervalTime); } /** * 指定的執(zhí)行次數(shù)和間隔時間 * * @param actionCount 指定執(zhí)行次數(shù) * @param intervalTime 指定間隔時間 */ public TimerTaskEvent(int actionCount, int intervalTime) { this(0, false, 0, actionCount, intervalTime); } /** * 提交后指定的時間無限制執(zhí)行 * * @param intervalTime 指定間隔時間 */ public TimerTaskEvent(int intervalTime) { this(0, false, 0, -1, intervalTime); } public long getStartTime { return startTime; } public void setStartTime(long startTime) { this.startTime = startTime; } public boolean isStartAction { return startAction; } public void setStartAction(boolean startAction) { this.startAction = startAction; } public long getEndTime { return endTime; } public void setEndTime(long endTime) { this.endTime = endTime; } public int getActionCount { return actionCount; } public void setActionCount(int actionCount) { this.actionCount = actionCount; } public int getIntervalTime { return intervalTime; } public void setIntervalTime(int intervalTime) { this.intervalTime = intervalTime; } }
這里是任務(wù)模型和定時器任務(wù)模型;
package net.sz.engine.thread; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; import net.sz.engine.structs.ObjectGlobal; import net.sz.engine.utils.MailUtil; import net.sz.engine.utils.StringUtil; import org.apache.log4j.Logger; import org.jboss.jandex.Main; /** * 線程模型 * <br> * author 失足程序員<br> * mail 492794628@qq.com<br> * phone 13882122019<br> */ public class ThreadModel implements Runnable { private static final Logger log = Logger.getLogger(ThreadModel.class); private static long threadID = 0; protected static final Object SYN_OBJECT = new Object; protected long tid; protected String name; protected long lastSendMail = 0; protected final ArrayList<MyThread> threads = new ArrayList<>; /** * 任務(wù)列表 線程安全的任務(wù)列表 */ //protected final List<TaskModel> taskQueue = new ArrayList<>; protected final ConcurrentLinkedQueue<TaskEvent> taskQueue = new ConcurrentLinkedQueue<>; /** * */ protected final List<TimerTaskEvent> timerQueue = new ArrayList<>; // false標(biāo)識刪除線程 protected volatile boolean runing = true; public ThreadModel(ThreadGroup group) { this(group, "無名", 1); } public ThreadModel(String name) { this(ThreadPool.UnknownThreadGroup, name, 1); } public ThreadModel(ThreadGroup group, String name, int threadCount) { this(group, name, threadCount, null); } public ThreadModel(ThreadGroup group, String name, int threadCount, Runnable runnable) { synchronized (SYN_OBJECT) { threadID++; tid = threadID; } for (int i = 1; i <= threadCount; i++) { MyThread thread; if (runnable == null) { thread = new MyThread(tid, group, this, name + "-" + tid + "-" + i); } else { thread = new MyThread(tid, group, runnable, name + "-" + tid + "-" + i); } thread.start; threads.add(thread); } this.name = name; } /** * 線程名字 * * @return */ public String getName { return name; } /** * 獲取線程的自定義id * * @return */ public long getId { return this.tid; } /** * 增加新的任務(wù) 每增加一個新任務(wù),都要喚醒任務(wù)隊列 * * @param runnable */ public void addTask(TaskEvent runnable) { taskQueue.add(runnable); synchronized (taskQueue) { /* 喚醒隊列, 開始執(zhí)行 */ taskQueue.notifyAll; } } /** * 向線程添加定時器任務(wù) * * @param runnable */ public void addTimer(TimerTaskEvent runnable) { synchronized (timerQueue) { if (runing) { //一開始執(zhí)行一次 if (runnable.startAction) { addTask(runnable); } timerQueue.add(runnable); } else { log.error("線程已經(jīng)停止"); } } } // <editor-fold defaultstate="collapsed" desc="定時器線程執(zhí)行器 public void timerRun"> /** * 定時器線程執(zhí)行器 */ public void timerRun { ArrayList<TimerTaskEvent> taskModels; synchronized (timerQueue) { // 隊列不為空的情況下 取出隊列定時器任務(wù) taskModels = new ArrayList<>(timerQueue); } if (!taskModels.isEmpty) { for (TimerTaskEvent timerEvent : taskModels) { int execCount = timerEvent.getRunOther.getintValue("Execcount"); long lastTime = timerEvent.getRunOther.getlongValue("LastExecTime"); long nowTime = System.currentTimeMillis; if (lastTime == 0) { timerEvent.getRunOther.put("LastExecTime", nowTime); } else if (timerEvent.isCancel) { //如果任務(wù)已經(jīng)取消 synchronized (timerQueue) { timerQueue.remove(timerEvent); } log.debug("清理定時器任務(wù):" + timerEvent.getClass.getName); } else if (nowTime > timerEvent.getStartTime // 是否滿足開始時間 && (nowTime - timerEvent.getSubmitTime > timerEvent .getIntervalTime)// 提交以后是否滿足了間隔時間 && (timerEvent.getEndTime <= 0 || nowTime < timerEvent .getEndTime) // 判斷結(jié)束時間 && (nowTime - lastTime >= timerEvent .getIntervalTime)) // 判斷上次執(zhí)行到目前是否滿足間隔時間 { // 提交執(zhí)行定時器最先執(zhí)行 this.addTask(timerEvent); // 記錄 execCount++; timerEvent.getRunOther.put("Execcount", execCount); timerEvent.getRunOther.put("LastExecTime", nowTime); nowTime = System.currentTimeMillis; // 判斷刪除條件 if ((timerEvent.getEndTime > 0 && nowTime < timerEvent.getEndTime) || (timerEvent.getActionCount > 0 && timerEvent.getActionCount <= execCount)) { synchronized (timerQueue) { timerQueue.remove(timerEvent); } log.debug("清理定時器任務(wù):" + timerEvent.getClass.getName); } } } } } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="查看線程堆棧 public void showStackTrace"> /** * * 查看線程堆棧 */ public void showStackTrace { StringBuilder buf = new StringBuilder; for (MyThread currentThread : threads) { long procc = System.currentTimeMillis - currentThread.getLastExecuteTime; if (procc > 5 * 1000 && procc < 864000000L) {//小于10天//因為多線程操作時間可能不準(zhǔn)確 buf.append("線程[") .append(currentThread.getName) .append("]可能已卡死 -> ") .append(procc / 1000f) .append("s\n ") .append("執(zhí)行任務(wù):") .append(currentThread.getLastCommand.getClass.getName); try { StackTraceElement elements = currentThread.getStackTrace; for (int i = 0; i < elements.length; i++) { buf.append("\n ") .append(elements[i].getClassName) .append(".") .append(elements[i].getMethodName) .append("(").append(elements[i].getFileName) .append(";") .append(elements[i].getLineNumber).append(")"); } } catch (Exception e) { buf.append(e); } buf.append("\n++++++++++++++++++++++++++++++++++"); } } String toString = buf.toString; if (!StringUtil.isNullOrEmpty(toString)) { log.error(toString); if (System.currentTimeMillis - lastSendMail > 5 * 60 * 1000) { lastSendMail = System.currentTimeMillis; MailUtil.sendMail("線程執(zhí)行已卡死 -> 游戲id-" + ObjectGlobal.GameID + " 平臺-" + ObjectGlobal.Platform + " 服務(wù)器id-" + ObjectGlobal.ServerID, toString); } } } // </editor-fold> @Override public void run { MyThread currentThread = (MyThread) Thread.currentThread; while (runing) { while (taskQueue.isEmpty && runing) { try { /* 任務(wù)隊列為空,則等待有新任務(wù)加入從而被喚醒 */ synchronized (taskQueue) { taskQueue.wait(500); } } catch (InterruptedException ie) { log.error(ie); } } /* 取出任務(wù)執(zhí)行 */ if (runing) { currentThread.lastCommand = null; currentThread.lastCommand = taskQueue.poll; } if (currentThread.lastCommand != null) { if (currentThread.lastCommand.isCancel) { //如果任務(wù)已經(jīng)取消 continue; } /* 執(zhí)行任務(wù) */ // r.setSubmitTimeL; currentThread.lastExecuteTime = System.currentTimeMillis; try { currentThread.lastCommand.run; } catch (Exception e) { log.error("工人<“" + currentThread.getName + "”> 執(zhí)行任務(wù)<" + currentThread.lastCommand.getClass.getName + "> 遇到錯誤: ", e); } long timeL1 = System.currentTimeMillis - currentThread.lastExecuteTime; if (timeL1 <= 20) { } else if (timeL1 <= 100L) { log.info("工人<“" + currentThread.getName + "”> 完成了任務(wù):" + currentThread.lastCommand.toString + " 執(zhí)行耗時:" + timeL1); } else if (timeL1 <= 200L) { log.info("工人<“" + currentThread.getName + "”> 長時間執(zhí)行 完成任務(wù):" + currentThread.lastCommand.toString + " “考慮”任務(wù)腳本邏輯 耗時:" + timeL1); } else { log.info("工人<“" + currentThread.getName + "”> 超長時間執(zhí)行完成 任務(wù):" + currentThread.lastCommand.toString + " “考慮是否應(yīng)該刪除”任務(wù)腳本 耗時:" + timeL1); } currentThread.lastExecuteTime = 0; } } log.error("線程結(jié)束, 工人<“" + Thread.currentThread.getName + "”>退出"); } /** * 自定義線程 */ public class MyThread extends Thread { /** * * @param tid 自定義線程id * @param group 分組 * @param run 執(zhí)行方法 * @param name 線程名稱 */ public MyThread(long tid, ThreadGroup group, Runnable run, String name) { super(group, run, name); this._id = tid; } //線程的自定義id public long _id; //正在執(zhí)行的任務(wù) public volatile TaskEvent lastCommand; //開始執(zhí)行任務(wù)的時間 public volatile long lastExecuteTime = 0; public TaskEvent getLastCommand { return lastCommand; } public long getLastExecuteTime { return lastExecuteTime; } /** * 返回線程自定義id * * @return */ @Override public long getId { return _id; } } /** * 停止線程,設(shè)置線程的停止?fàn)顟B(tài),并不會馬上終止線程 */ public void stop { this.runing = false; } public boolean isRuning { return runing; } @Override public String toString { return "Thread{" + "tid=" + tid + ",Name=" + this.getName + '}'; } }
我從 ThreadModel 構(gòu)造函數(shù)的
public ThreadModel(ThreadGroup group, String name, int threadCount, Runnable runnable) { synchronized (SYN_OBJECT) { threadID++; tid = threadID; } for (int i = 1; i <= threadCount; i++) { MyThread thread; if (runnable == null) { thread = new MyThread(tid, group, this, name + "-" + tid + "-" + i); } else { thread = new MyThread(tid, group, runnable, name + "-" + tid + "-" + i); } thread.start; threads.add(thread); } this.name = name; }
可以看出,這里我運行聲明一個或者多個 MyThread 線程類
為什么要這樣考慮呢打個比方,如果是處理日志的寫入數(shù)據(jù)這種,沒有共享數(shù)據(jù),沒有線程臨界區(qū)的處理流程,我可以考慮使用N個線程去處理這樣的工作;不會產(chǎn)生臟數(shù)據(jù);
如果是想組隊請求,技能施法這種處理,我需要單隊列處理,那么threadmodel里面肯定只有一個MyThread 這樣不算阻塞模式串行執(zhí)行(或隊列執(zhí)行)把共享數(shù)據(jù)和線程臨界區(qū)的問題也解決了不再依賴鎖;
字很丑,請見諒
上面圖片看出,在每一個threadmodel 里面都會兩個隊列,一個timertaskevent,一個是taskevent,會存在一個全局的timer thread;
全局的 timer thread 的作用是用來定時去處理和發(fā)現(xiàn) threadmodel里面timertaskevent需要執(zhí)行了,就把他加入到taskevent隊里里面;最終執(zhí)行是taskevent隊列
timertaskevent為什么要存儲在對應(yīng)的threadmodel里面呢,那是因為比如,我A線程(threadmodel實例)運行一段時間后需要關(guān)閉,釋放資源了,那么我還要去其他地方查找對應(yīng)的timertask并移除掉;
package net.sz.engine.thread; import java.util.HashMap; import java.util.Map; /** * * <br> * author 失足程序員<br> * mail 492794628@qq.com<br> * phone 13882122019<br> */ class TimerThread extends Thread { private static final Object SYN_OBJECT = new Object; public TimerThread { super(ThreadPool.GloblThreadGroup, "Global Timer Thread"); } @Override public void run { while (true) { synchronized (SYN_OBJECT) { try { SYN_OBJECT.wait(2); } catch (InterruptedException ex) { } } HashMap<Long, ThreadModel> hashMap = new HashMap<>(ThreadPool.getThreadMap); for (Map.Entry<Long, ThreadModel> entrySet : hashMap.entrySet) { Long key = entrySet.getKey; ThreadModel value = entrySet.getValue; value.timerRun; } } } }
線程模型的管理器
package net.sz.engine.thread; import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import net.sz.engine.script.manager.ScriptManager; import net.sz.engine.timer.GlobTimerEvent; import net.sz.engine.timer.PrintlnServerMemoryTimerEvent; import org.apache.log4j.Logger; /** * 線程管理器 * * <br> * author 失足程序員<br> * mail 492794628@qq.com<br> * phone 13882122019<br> */ public class ThreadPool { static private final Logger log = Logger.getLogger(ThreadPool.class); static public final long GloblThread; static private final TimerThread GloblTimerThread; static final long CheckThreadTimerThreadModel; static public final ThreadGroup GloblThreadGroup = new ThreadGroup("Global ThreadGroup"); static public final ThreadGroup UnknownThreadGroup = new ThreadGroup(GloblThreadGroup, "Unknown ThreadGroup"); static private final ConcurrentHashMap<Long, ThreadModel> threadMap = new ConcurrentHashMap<>; public static void main(String[] args) { ThreadPool.addTimerTask(GloblThread, new TimerTaskEvent(1000) { @Override public void run { log.error("ssssss"); } }); } static { //創(chuàng)建全局線程 GloblThread = addThreadModel(GloblThreadGroup, "GloblThread"); //執(zhí)行指定任務(wù)定時觸發(fā)腳步 addTimerTask(GloblThread, new GlobTimerEvent(ScriptManager.getInstance.getBaseScriptEntry)); //查詢服務(wù)器消耗定時模型 addTimerTask(GloblThread, new PrintlnServerMemoryTimerEvent); //創(chuàng)建定時器線程 GloblTimerThread = new TimerThread; GloblTimerThread.start; //檢查線程卡死情況 CheckThreadTimerThreadModel = addThreadModel(GloblThreadGroup, "Check Thread Timer Event"); addTimerTask(CheckThreadTimerThreadModel, new CheckThreadTimerEvent); } /** * 刪除指定id線程模型的時候回設(shè)置狀態(tài)為停止?fàn)顟B(tài) * * @param tid * @return */ static public ThreadModel remove(long tid) { ThreadModel remove = threadMap.remove(tid); if (remove != null) { remove.stop; } return remove; } /** * 獲取線程池中所有線程 * * @return */ static public ConcurrentHashMap<Long, ThreadModel> getThreadMap { return threadMap; } /** * 獲取線程池的一個線程 * * @param threadId * @return */ static public ThreadModel getThreadModel(long threadId) { ThreadModel get = threadMap.get(threadId); if (get == null) { log.error("無法找到線程模型:" + threadId, new Exception("無法找到線程模型:" + threadId)); } return get; } /** * 向線程池注冊一個線程 * <br> * 默認(rèn)分組 UnknownThreadGroup * * @param name 線程名稱 * @return */ static public long addThreadModel(String name) { return addThreadModel(UnknownThreadGroup, name); } /** * 向線程池注冊一個線程 * <br> * 默認(rèn)分組 UnknownThreadGroup * * @param name 線程名稱 * @param threadcount 線程量 * @return */ static public long addThreadModel(String name, int threadcount) { return addThreadModel(UnknownThreadGroup, name, threadcount); } /** * 向線程池注冊一個線程 * * @param group 線程分組信息 * @param name 線程名稱 * @return */ static public long addThreadModel(ThreadGroup group, String name) { return addThreadModel(group, name, 1); } /** * 向線程池注冊一個線程 * * @param group 線程分組信息 * @param name 線程名稱 * @param threadcount 線程量 * @return */ static public long addThreadModel(ThreadGroup group, String name, int threadcount) { return addThreadModel(group, name, null, threadcount); } /** * 向線程池注冊一個線程 * * @param group 線程分組信息 * @param name 線程名稱 * @param runnable * @param threadcount 線程量 * @return */ static public long addThreadModel(ThreadGroup group, String name, Runnable runnable, int threadcount) { ThreadModel threadModel = new ThreadModel(group, name, threadcount, runnable); return addThreadModel(threadModel); } /** * 向線程池注冊一個線程 * * @param threadModel */ static public long addThreadModel(ThreadModel threadModel) { threadMap.put(threadModel.getId, threadModel); return threadModel.getId; } /** * 添加任務(wù) * * @param threadId * @param task * @return */ static public boolean addTask(long threadId, TaskEvent task) { ThreadModel threadModel = getThreadModel(threadId); if (threadModel != null) { threadModel.addTask(task); return true; } return false; } /** * 添加定時器任務(wù) * * @param threadId * @param task * @return */ static public boolean addTimerTask(long threadId, TimerTaskEvent task) { ThreadModel threadModel = getThreadModel(threadId); if (threadModel != null) { threadModel.addTimer(task); return true; } return false; } /** * 添加任務(wù),添加任務(wù)到當(dāng)前線程 * * @param task * @return */ static public boolean addCurrentThreadTask(TaskEvent task) { Thread currentThread = Thread.currentThread; if (currentThread instanceof ThreadModel.MyThread) { long threadId = currentThread.getId; ThreadModel threadModel = getThreadModel(threadId); if (threadModel != null) { threadModel.addTask(task); return true; } } return false; } /** * 添加定時器任務(wù),添加任務(wù)到當(dāng)前線程 * * @param task * @return */ static public boolean addCurrentThreadTimerTask(TimerTaskEvent task) { Thread currentThread = Thread.currentThread; if (currentThread instanceof ThreadModel.MyThread) { long threadId = currentThread.getId; ThreadModel threadModel = getThreadModel(threadId); if (threadModel != null) { threadModel.addTimer(task); return true; } } return false; } }
接下來我們看看使用情況
上篇文章中線程介紹代碼
public static void main(String[] args) throws InterruptedException { //線程并行情況,有多個線程執(zhí)行多個任務(wù)/函數(shù) new Thread(new Run1).start; new Thread(new Run2).start; } //任務(wù)1 static class Run1 implements Runnable { @Override public void run { //執(zhí)行任務(wù)1 run1; //執(zhí)行任務(wù)3 run3; } } //任務(wù)2 static class Run2 implements Runnable { @Override public void run { //執(zhí)行任務(wù)3 run3; //執(zhí)行任務(wù)1 run1; //執(zhí)行任務(wù)2 run2; } } //任務(wù)1 public static void run1 { System.out.println("run1->" + System.currentTimeMillis); } //任務(wù)2 public static void run2 { System.out.println("run2->" + System.currentTimeMillis); } //任務(wù)3 public static void run3 { System.out.println("run3->" + System.currentTimeMillis); }
我把代碼切換模式
public static void main(String[] args) throws InterruptedException { //線程并行情況,有多個線程執(zhí)行多個任務(wù)/函數(shù) long test1 = ThreadPool.addThreadModel("測試線程-1"); long test2 = ThreadPool.addThreadModel("測試線程-2"); //添加任務(wù) ThreadPool.addTask(test1, new Run1); ThreadPool.addTask(test2, new Run2); //添加定時器任務(wù) ThreadPool.addTimerTask(test1, new TimerRun1); ThreadPool.addTimerTask(test2, new TimerRun2); } //任務(wù)1 static class Run1 extends TaskEvent { @Override public void run { //執(zhí)行任務(wù)1 run1; //執(zhí)行任務(wù)3 run3; } } //任務(wù)1 static class TimerRun1 extends TimerTaskEvent { public TimerRun1 { super(500);//500毫秒無限制執(zhí)行 } @Override public void run { //執(zhí)行任務(wù)1 run1; //執(zhí)行任務(wù)3 run3; } } //任務(wù)2 static class Run2 extends TaskEvent { @Override public void run { //執(zhí)行任務(wù)3 run3; //執(zhí)行任務(wù)1 run1; //執(zhí)行任務(wù)2 run2; } } //任務(wù)2 static class TimerRun2 extends TimerTaskEvent { public TimerRun2 { super(500);//500毫秒無限制執(zhí)行 } @Override public void run { //執(zhí)行任務(wù)3 run3; //執(zhí)行任務(wù)1 run1; //執(zhí)行任務(wù)2 run2; } } //任務(wù)1 public static void run1 { System.out.println("run1->" + System.currentTimeMillis); } //任務(wù)2 public static void run2 { System.out.println("run2->" + System.currentTimeMillis); } //任務(wù)3 public static void run3 { System.out.println("run3->" + System.currentTimeMillis); }
接下來我們看看執(zhí)行效果
run1->1472120543013 run3->1472120543013 run3->1472120543017 run1->1472120543017 run2->1472120543017 run1->1472120543517 run3->1472120543517 run2->1472120543517 run1->1472120544018 run3->1472120544018 run2->1472120544018 run1->1472120544520 run3->1472120544520 run2->1472120544520 run1->1472120545021 run3->1472120545021 run2->1472120545021 run1->1472120545521 run3->1472120545521
一切正常;
這就是我的自定義線程模型;
到這里我的自定義線程模型就算介紹完成了;
那么優(yōu)缺點在哪里呢?
優(yōu)點是,數(shù)據(jù)流程控制很清晰,包括現(xiàn)在執(zhí)行情況,以及線程卡死監(jiān)控和任務(wù) 的定時器執(zhí)行;
缺點,這個自定義線程模型依然不可能解決線程數(shù)據(jù)安全和臨界區(qū)問題,在適當(dāng)?shù)臅r候依然需要靠鎖或者其他形式來解決;
不足之處希望大神們指出,我好即時糾正。
相關(guān)文章
詳解SimpleDateFormat的線程安全問題與解決方案
這篇文章主要介紹了SimpleDateFormat的線程安全問題與解決方案,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-03-03SpringBoot實現(xiàn)短信發(fā)送及手機驗證碼登錄
本文主要介紹了SpringBoot實現(xiàn)短信發(fā)送及手機驗證碼登錄,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07mybatis plus generator 根據(jù)數(shù)據(jù)庫自動生成實體類的實現(xiàn)示例
本文主要介紹了mybatis plus generator 根據(jù)數(shù)據(jù)庫自動生成實體類的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09IDEA導(dǎo)入Springboot項目,注解和pom文件不識別的解決
這篇文章主要介紹了IDEA導(dǎo)入Springboot項目,注解和pom文件不識別的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04Spring boot應(yīng)用啟動后首次訪問很慢的解決方案
這篇文章主要介紹了Spring boot應(yīng)用啟動后首次訪問很慢的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06詳解mybatis-plus使用@EnumValue注解的方式對枚舉類型的處理
這篇文章主要介紹了詳解mybatis-plus使用@EnumValue注解的方式對枚舉類型的處理,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12