java自定義線程模型處理方法分享
看過(guò)我之前文章的園友可能知道我是做游戲開發(fā),我的很多思路和出發(fā)點(diǎn)是按照游戲思路來(lái)處理的,所以和web的話可能會(huì)有沖突,不相符合。
來(lái)說(shuō)說(shuō)為啥我要自定義線程模型呢?
按照我做的mmorpg或者mmoarpg游戲劃分,線程被劃分為,主線程,全局同步線程,聊天線程,組隊(duì)線程,地圖線程,以及地圖消息分發(fā)派送線程等;
一些列,都需要根據(jù)我的劃分,以及數(shù)據(jù)流向做控制。
游戲服務(wù)器,主要要做的事情,肯定是接受玩家的 命令請(qǐng)求 -> 相應(yīng)的操作 -> 返回結(jié)果;
在服務(wù)器端所有的消息都會(huì)注冊(cè)到消息管理器里,然后消息在注冊(cè)的時(shí)候會(huì)指定線程模型,
如果消息需要提交到玩家所在地圖線程進(jìn)行處理的話注冊(cè)消息的時(shí)候就要把線程模型用(地圖消息分發(fā)派送線程);
下面我們先來(lái)分析線程模型;
在看線程模型代碼之前我先看看我的任務(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;
//運(yùn)行時(shí)數(shù)據(jù)
private transient final ObjectAttribute runOther = new ObjectAttribute;
//任務(wù)創(chuàng)建的時(shí)間
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;
/**
* 定時(shí)器執(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í)行的時(shí)間
*/
protected long startTime;
/**
* 是否一開始執(zhí)行一次
*/
protected boolean startAction;
/**
* 結(jié)束時(shí)間
*/
protected long endTime;
/**
* 執(zhí)行次數(shù)
*/
protected int actionCount;
/**
* 間隔執(zhí)行時(shí)間
*/
protected int intervalTime;
/**
*
* @param startTime 指定開始時(shí)間
* @param isStartAction 是否一開始就執(zhí)行一次
* @param endTime 指定結(jié)束時(shí)間
* @param actionCount 指定執(zhí)行次數(shù)
* @param intervalTime 指定間隔時(shí)間
*/
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í)行時(shí)間
*
* @param startTime 指定開始時(shí)間
* @param isStartAction 是否一開始就執(zhí)行一次
* @param actionCount 指定執(zhí)行次數(shù)
* @param intervalTime 指定間隔時(shí)間
*/
public TimerTaskEvent(long startTime, boolean isStartAction, int actionCount, int intervalTime) {
this(startTime, isStartAction, 0, actionCount, intervalTime);
}
/**
* 指定結(jié)束時(shí)間已結(jié)束時(shí)間為準(zhǔn),執(zhí)行次數(shù)不一定夠
*
* @param isStartAction 是否一開始就執(zhí)行一次
* @param endTime 指定結(jié)束時(shí)間
* @param actionCount 指定執(zhí)行次數(shù)
* @param intervalTime 指定間隔時(shí)間
*
*/
public TimerTaskEvent(boolean isStartAction, long endTime, int actionCount, int intervalTime) {
this(0, isStartAction, endTime, actionCount, intervalTime);
}
/**
* 指定開始時(shí)間,和結(jié)束時(shí)間
*
* @param startTime 指定開始時(shí)間
* @param endTime 指定結(jié)束時(shí)間
* @param intervalTime 指定間隔時(shí)間
*/
public TimerTaskEvent(long startTime, long endTime, int intervalTime) {
this(startTime, false, endTime, -1, intervalTime);
}
/**
* 指定的執(zhí)行次數(shù)和間隔時(shí)間
*
* @param actionCount 指定執(zhí)行次數(shù)
* @param intervalTime 指定間隔時(shí)間
*/
public TimerTaskEvent(int actionCount, int intervalTime) {
this(0, false, 0, actionCount, intervalTime);
}
/**
* 提交后指定的時(shí)間無(wú)限制執(zhí)行
*
* @param intervalTime 指定間隔時(shí)間
*/
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ù)模型和定時(shí)器任務(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)識(shí)刪除線程
protected volatile boolean runing = true;
public ThreadModel(ThreadGroup group) {
this(group, "無(wú)名", 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ù) 每增加一個(gè)新任務(wù),都要喚醒任務(wù)隊(duì)列
*
* @param runnable
*/
public void addTask(TaskEvent runnable) {
taskQueue.add(runnable);
synchronized (taskQueue) {
/* 喚醒隊(duì)列, 開始執(zhí)行 */
taskQueue.notifyAll;
}
}
/**
* 向線程添加定時(shí)器任務(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="定時(shí)器線程執(zhí)行器 public void timerRun">
/**
* 定時(shí)器線程執(zhí)行器
*/
public void timerRun {
ArrayList<TimerTaskEvent> taskModels;
synchronized (timerQueue) {
// 隊(duì)列不為空的情況下 取出隊(duì)列定時(shí)器任務(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("清理定時(shí)器任務(wù):" + timerEvent.getClass.getName);
} else if (nowTime > timerEvent.getStartTime // 是否滿足開始時(shí)間
&& (nowTime - timerEvent.getSubmitTime > timerEvent
.getIntervalTime)// 提交以后是否滿足了間隔時(shí)間
&& (timerEvent.getEndTime <= 0 || nowTime < timerEvent
.getEndTime) // 判斷結(jié)束時(shí)間
&& (nowTime - lastTime >= timerEvent
.getIntervalTime)) // 判斷上次執(zhí)行到目前是否滿足間隔時(shí)間
{
// 提交執(zhí)行定時(shí)器最先執(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("清理定時(shí)器任務(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天//因?yàn)槎嗑€程操作時(shí)間可能不準(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 + " 平臺(tái)-" + 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ù)隊(duì)列為空,則等待有新任務(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 + "> 遇到錯(cuò)誤: ", e);
}
long timeL1 = System.currentTimeMillis - currentThread.lastExecuteTime;
if (timeL1 <= 20) {
} else if (timeL1 <= 100L) {
log.info("工人<“" + currentThread.getName + "”> 完成了任務(wù):" + currentThread.lastCommand.toString + " 執(zhí)行耗時(shí):" + timeL1);
} else if (timeL1 <= 200L) {
log.info("工人<“" + currentThread.getName + "”> 長(zhǎng)時(shí)間執(zhí)行 完成任務(wù):" + currentThread.lastCommand.toString + " “考慮”任務(wù)腳本邏輯 耗時(shí):" + timeL1);
} else {
log.info("工人<“" + currentThread.getName + "”> 超長(zhǎng)時(shí)間執(zhí)行完成 任務(wù):" + currentThread.lastCommand.toString + " “考慮是否應(yīng)該刪除”任務(wù)腳本 耗時(shí):" + 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ù)的時(shí)間
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),并不會(huì)馬上終止線程
*/
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;
}
可以看出,這里我運(yùn)行聲明一個(gè)或者多個(gè) MyThread 線程類
為什么要這樣考慮呢打個(gè)比方,如果是處理日志的寫入數(shù)據(jù)這種,沒有共享數(shù)據(jù),沒有線程臨界區(qū)的處理流程,我可以考慮使用N個(gè)線程去處理這樣的工作;不會(huì)產(chǎn)生臟數(shù)據(jù);
如果是想組隊(duì)請(qǐng)求,技能施法這種處理,我需要單隊(duì)列處理,那么threadmodel里面肯定只有一個(gè)MyThread 這樣不算阻塞模式串行執(zhí)行(或隊(duì)列執(zhí)行)把共享數(shù)據(jù)和線程臨界區(qū)的問(wèn)題也解決了不再依賴鎖;
字很丑,請(qǐng)見諒

上面圖片看出,在每一個(gè)threadmodel 里面都會(huì)兩個(gè)隊(duì)列,一個(gè)timertaskevent,一個(gè)是taskevent,會(huì)存在一個(gè)全局的timer thread;
全局的 timer thread 的作用是用來(lái)定時(shí)去處理和發(fā)現(xiàn) threadmodel里面timertaskevent需要執(zhí)行了,就把他加入到taskevent隊(duì)里里面;最終執(zhí)行是taskevent隊(duì)列
timertaskevent為什么要存儲(chǔ)在對(duì)應(yīng)的threadmodel里面呢,那是因?yàn)楸热?,我A線程(threadmodel實(shí)例)運(yùn)行一段時(shí)間后需要關(guān)閉,釋放資源了,那么我還要去其他地方查找對(duì)應(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ù)定時(shí)觸發(fā)腳步
addTimerTask(GloblThread, new GlobTimerEvent(ScriptManager.getInstance.getBaseScriptEntry));
//查詢服務(wù)器消耗定時(shí)模型
addTimerTask(GloblThread, new PrintlnServerMemoryTimerEvent);
//創(chuàng)建定時(shí)器線程
GloblTimerThread = new TimerThread;
GloblTimerThread.start;
//檢查線程卡死情況
CheckThreadTimerThreadModel = addThreadModel(GloblThreadGroup, "Check Thread Timer Event");
addTimerTask(CheckThreadTimerThreadModel, new CheckThreadTimerEvent);
}
/**
* 刪除指定id線程模型的時(shí)候回設(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;
}
/**
* 獲取線程池的一個(gè)線程
*
* @param threadId
* @return
*/
static public ThreadModel getThreadModel(long threadId) {
ThreadModel get = threadMap.get(threadId);
if (get == null) {
log.error("無(wú)法找到線程模型:" + threadId, new Exception("無(wú)法找到線程模型:" + threadId));
}
return get;
}
/**
* 向線程池注冊(cè)一個(gè)線程
* <br>
* 默認(rèn)分組 UnknownThreadGroup
*
* @param name 線程名稱
* @return
*/
static public long addThreadModel(String name) {
return addThreadModel(UnknownThreadGroup, name);
}
/**
* 向線程池注冊(cè)一個(gè)線程
* <br>
* 默認(rèn)分組 UnknownThreadGroup
*
* @param name 線程名稱
* @param threadcount 線程量
* @return
*/
static public long addThreadModel(String name, int threadcount) {
return addThreadModel(UnknownThreadGroup, name, threadcount);
}
/**
* 向線程池注冊(cè)一個(gè)線程
*
* @param group 線程分組信息
* @param name 線程名稱
* @return
*/
static public long addThreadModel(ThreadGroup group, String name) {
return addThreadModel(group, name, 1);
}
/**
* 向線程池注冊(cè)一個(gè)線程
*
* @param group 線程分組信息
* @param name 線程名稱
* @param threadcount 線程量
* @return
*/
static public long addThreadModel(ThreadGroup group, String name, int threadcount) {
return addThreadModel(group, name, null, threadcount);
}
/**
* 向線程池注冊(cè)一個(gè)線程
*
* @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);
}
/**
* 向線程池注冊(cè)一個(gè)線程
*
* @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;
}
/**
* 添加定時(shí)器任務(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;
}
/**
* 添加定時(shí)器任務(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;
}
}
接下來(lái)我們看看使用情況
上篇文章中線程介紹代碼
public static void main(String[] args) throws InterruptedException {
//線程并行情況,有多個(gè)線程執(zhí)行多個(gè)任務(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 {
//線程并行情況,有多個(gè)線程執(zhí)行多個(gè)任務(wù)/函數(shù)
long test1 = ThreadPool.addThreadModel("測(cè)試線程-1");
long test2 = ThreadPool.addThreadModel("測(cè)試線程-2");
//添加任務(wù)
ThreadPool.addTask(test1, new Run1);
ThreadPool.addTask(test2, new Run2);
//添加定時(shí)器任務(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毫秒無(wú)限制執(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毫秒無(wú)限制執(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);
}
接下來(lái)我們看看執(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)缺點(diǎn)在哪里呢?
優(yōu)點(diǎn)是,數(shù)據(jù)流程控制很清晰,包括現(xiàn)在執(zhí)行情況,以及線程卡死監(jiān)控和任務(wù) 的定時(shí)器執(zhí)行;
缺點(diǎn),這個(gè)自定義線程模型依然不可能解決線程數(shù)據(jù)安全和臨界區(qū)問(wèn)題,在適當(dāng)?shù)臅r(shí)候依然需要靠鎖或者其他形式來(lái)解決;
不足之處希望大神們指出,我好即時(shí)糾正。
相關(guān)文章
詳解SimpleDateFormat的線程安全問(wèn)題與解決方案
這篇文章主要介紹了SimpleDateFormat的線程安全問(wèn)題與解決方案,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03
從源碼角度看spring mvc的請(qǐng)求處理過(guò)程
這篇文章主要介紹了從源碼角度看spring mvc的請(qǐng)求處理過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06
SpringBoot實(shí)現(xiàn)短信發(fā)送及手機(jī)驗(yàn)證碼登錄
本文主要介紹了SpringBoot實(shí)現(xiàn)短信發(fā)送及手機(jī)驗(yàn)證碼登錄,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
mybatis plus generator 根據(jù)數(shù)據(jù)庫(kù)自動(dòng)生成實(shí)體類的實(shí)現(xiàn)示例
本文主要介紹了mybatis plus generator 根據(jù)數(shù)據(jù)庫(kù)自動(dòng)生成實(shí)體類的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
IDEA導(dǎo)入Springboot項(xiàng)目,注解和pom文件不識(shí)別的解決
這篇文章主要介紹了IDEA導(dǎo)入Springboot項(xiàng)目,注解和pom文件不識(shí)別的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Spring boot應(yīng)用啟動(dòng)后首次訪問(wèn)很慢的解決方案
這篇文章主要介紹了Spring boot應(yīng)用啟動(dòng)后首次訪問(wèn)很慢的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
詳解mybatis-plus使用@EnumValue注解的方式對(duì)枚舉類型的處理
這篇文章主要介紹了詳解mybatis-plus使用@EnumValue注解的方式對(duì)枚舉類型的處理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Spring實(shí)戰(zhàn)之獲取方法返回值操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之獲取方法返回值操作,涉及spring配置文件與方法返回值操作相關(guān)使用技巧,需要的朋友可以參考下2019-12-12
Spring啟動(dòng)過(guò)程源碼分析及簡(jiǎn)介
本文是通過(guò)AnnotationConfigApplicationContext讀取配置類來(lái)一步一步去了解Spring的啟動(dòng)過(guò)程。本文重點(diǎn)給大家介紹Spring啟動(dòng)過(guò)程源碼分析及基本概念,感興趣的朋友一起看看吧2021-10-10

