看我是如何处理自定义线程模型---java
看过我之前文章的园友可能知道我是做游戏开发,我的很多思路和出发点是按照游戏思路来处理的,所以和web的话可能会有冲突,不相符合。
来说说为啥我要自定义线程模型呢?
按照我做的mmorpg或者mmoarpg游戏划分,线程被划分为,主线程,全局同步线程,聊天线程,组队线程,地图线程,以及地图消息分发派送线程等;
一些列,都需要根据我的划分,以及数据流向做控制。
游戏服务器,主要要做的事情,肯定是接受玩家的 命令请求 -> 相应的操作 -> 返回结果; 在服务器端所有的消息都会注册到消息管理器里,然后消息在注册的时候会指定线程模型, 如果消息需要提交到玩家所在地图线程进行处理的话注册消息的时候就要把线程模型用(地图消息分发派送线程);
下面我们先来分析线程模型;
在看线程模型代码之前我先看看我的任务模型
1 package net.sz.engine.thread; 2 3 import java.io.Serializable; 4 import org.apache.log4j.Logger; 5 import net.sz.engine.structs.ObjectAttribute; 6 import net.sz.engine.structs.ObjectGlobal; 7 8 /** 9 * 任务模型 10 * 11 * <br> 12 * author 失足程序员<br> 13 * mail 492794628@qq.com<br> 14 * phone 13882122019<br> 15 */ 16 public abstract class TaskEvent implements Serializable, Cloneable { 17 18 private static final Logger log = Logger.getLogger(TaskEvent.class); 19 private static final long serialVersionUID = 4196020659994845804L; 20 21 //运行时数据 22 private transient final ObjectAttribute runOther = new ObjectAttribute(); 23 //任务创建的时间 24 protected long createTime; 25 //任务的唯一id 26 protected long taskId; 27 //取消的任务 28 protected boolean cancel = false; 29 30 public TaskEvent() { 31 this.runOther.put("submitTime", System.currentTimeMillis()); 32 createTime = System.currentTimeMillis(); 33 cancel = false; 34 taskId = ObjectGlobal.getUUID(); 35 } 36 37 public long getCreateTime() { 38 return createTime; 39 } 40 41 public void setCreateTime(long createTime) { 42 this.createTime = createTime; 43 } 44 45 public long getSubmitTime() { 46 return this.runOther.getlongValue("submitTime"); 47 } 48 49 public ObjectAttribute getRunOther() { 50 return runOther; 51 } 52 53 public boolean isCancel() { 54 return cancel; 55 } 56 57 public void setCancel(boolean cancel) { 58 this.cancel = cancel; 59 } 60 61 public abstract void run(); 62 63 @Override 64 public Object clone() throws CloneNotSupportedException { 65 return super.clone(); //To change body of generated methods, choose Tools | Templates. 66 } 67 68 }
1 package net.sz.engine.thread; 2 3 /** 4 * 定时器执行器 5 * 6 * <br> 7 * author 失足程序员<br> 8 * mail 492794628@qq.com<br> 9 * phone 13882122019<br> 10 */ 11 public abstract class TimerTaskEvent extends TaskEvent { 12 13 private static final long serialVersionUID = -8331296295264699207L; 14 15 /** 16 * 开始执行的时间 17 */ 18 protected long startTime; 19 20 /** 21 * 是否一开始执行一次 22 */ 23 protected boolean startAction; 24 25 /** 26 * 结束时间 27 */ 28 protected long endTime; 29 30 /** 31 * 执行次数 32 */ 33 protected int actionCount; 34 35 /** 36 * 间隔执行时间 37 */ 38 protected int intervalTime; 39 40 /** 41 * 42 * @param startTime 指定开始时间 43 * @param isStartAction 是否一开始就执行一次 44 * @param endTime 指定结束时间 45 * @param actionCount 指定执行次数 46 * @param intervalTime 指定间隔时间 47 */ 48 public TimerTaskEvent(long startTime, boolean isStartAction, long endTime, int actionCount, int intervalTime) { 49 super(); 50 this.startTime = startTime; 51 this.startAction = isStartAction; 52 this.endTime = endTime; 53 this.actionCount = actionCount; 54 this.intervalTime = intervalTime; 55 } 56 57 /** 58 * 指定任务的开始执行时间 59 * 60 * @param startTime 指定开始时间 61 * @param isStartAction 是否一开始就执行一次 62 * @param actionCount 指定执行次数 63 * @param intervalTime 指定间隔时间 64 */ 65 public TimerTaskEvent(long startTime, boolean isStartAction, int actionCount, int intervalTime) { 66 this(startTime, isStartAction, 0, actionCount, intervalTime); 67 } 68 69 /** 70 * 指定结束时间已结束时间为准,执行次数不一定够 71 * 72 * @param isStartAction 是否一开始就执行一次 73 * @param endTime 指定结束时间 74 * @param actionCount 指定执行次数 75 * @param intervalTime 指定间隔时间 76 * 77 */ 78 public TimerTaskEvent(boolean isStartAction, long endTime, int actionCount, int intervalTime) { 79 this(0, isStartAction, endTime, actionCount, intervalTime); 80 } 81 82 /** 83 * 指定开始时间,和结束时间 84 * 85 * @param startTime 指定开始时间 86 * @param endTime 指定结束时间 87 * @param intervalTime 指定间隔时间 88 */ 89 public TimerTaskEvent(long startTime, long endTime, int intervalTime) { 90 this(startTime, false, endTime, -1, intervalTime); 91 } 92 93 /** 94 * 指定的执行次数和间隔时间 95 * 96 * @param actionCount 指定执行次数 97 * @param intervalTime 指定间隔时间 98 */ 99 public TimerTaskEvent(int actionCount, int intervalTime) { 100 this(0, false, 0, actionCount, intervalTime); 101 } 102 103 /** 104 * 提交后指定的时间无限制执行 105 * 106 * @param intervalTime 指定间隔时间 107 */ 108 public TimerTaskEvent(int intervalTime) { 109 this(0, false, 0, -1, intervalTime); 110 } 111 112 public long getStartTime() { 113 return startTime; 114 } 115 116 public void setStartTime(long startTime) { 117 this.startTime = startTime; 118 } 119 120 public boolean isStartAction() { 121 return startAction; 122 } 123 124 public void setStartAction(boolean startAction) { 125 this.startAction = startAction; 126 } 127 128 public long getEndTime() { 129 return endTime; 130 } 131 132 public void setEndTime(long endTime) { 133 this.endTime = endTime; 134 } 135 136 public int getActionCount() { 137 return actionCount; 138 } 139 140 public void setActionCount(int actionCount) { 141 this.actionCount = actionCount; 142 } 143 144 public int getIntervalTime() { 145 return intervalTime; 146 } 147 148 public void setIntervalTime(int intervalTime) { 149 this.intervalTime = intervalTime; 150 } 151 152 }
这里是任务模型和定时器任务模型;
1 package net.sz.engine.thread; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.concurrent.ConcurrentLinkedQueue; 6 import net.sz.engine.structs.ObjectGlobal; 7 import net.sz.engine.utils.MailUtil; 8 import net.sz.engine.utils.StringUtil; 9 import org.apache.log4j.Logger; 10 import org.jboss.jandex.Main; 11 12 /** 13 * 线程模型 14 * <br> 15 * author 失足程序员<br> 16 * mail 492794628@qq.com<br> 17 * phone 13882122019<br> 18 */ 19 public class ThreadModel implements Runnable { 20 21 private static final Logger log = Logger.getLogger(ThreadModel.class); 22 private static long threadID = 0; 23 protected static final Object SYN_OBJECT = new Object(); 24 protected long tid; 25 protected String name; 26 protected long lastSendMail = 0; 27 28 protected final ArrayList<MyThread> threads = new ArrayList<>(); 29 /** 30 * 任务列表 线程安全的任务列表 31 */ 32 //protected final List<TaskModel> taskQueue = new ArrayList<>(); 33 protected final ConcurrentLinkedQueue<TaskEvent> taskQueue = new ConcurrentLinkedQueue<>(); 34 35 /** 36 * 37 */ 38 protected final List<TimerTaskEvent> timerQueue = new ArrayList<>(); 39 40 // false标识删除线程 41 protected volatile boolean runing = true; 42 43 public ThreadModel(ThreadGroup group) { 44 this(group, "无名", 1); 45 } 46 47 public ThreadModel(String name) { 48 this(ThreadPool.UnknownThreadGroup, name, 1); 49 } 50 51 public ThreadModel(ThreadGroup group, String name, int threadCount) { 52 this(group, name, threadCount, null); 53 } 54 55 public ThreadModel(ThreadGroup group, String name, int threadCount, Runnable runnable) { 56 synchronized (SYN_OBJECT) { 57 threadID++; 58 tid = threadID; 59 } 60 for (int i = 1; i <= threadCount; i++) { 61 MyThread thread; 62 if (runnable == null) { 63 thread = new MyThread(tid, group, this, name + "-" + tid + "-" + i); 64 } else { 65 thread = new MyThread(tid, group, runnable, name + "-" + tid + "-" + i); 66 } 67 thread.start(); 68 threads.add(thread); 69 } 70 this.name = name; 71 } 72 73 /** 74 * 线程名字 75 * 76 * @return 77 */ 78 public String getName() { 79 return name; 80 } 81 82 /** 83 * 获取线程的自定义id 84 * 85 * @return 86 */ 87 public long getId() { 88 return this.tid; 89 } 90 91 /** 92 * 增加新的任务 每增加一个新任务,都要唤醒任务队列 93 * 94 * @param runnable 95 */ 96 public void addTask(TaskEvent runnable) { 97 taskQueue.add(runnable); 98 99 synchronized (taskQueue) { 100 /* 唤醒队列, 开始执行 */ 101 taskQueue.notifyAll(); 102 } 103 } 104 105 /** 106 * 向线程添加定时器任务 107 * 108 * @param runnable 109 */ 110 public void addTimer(TimerTaskEvent runnable) { 111 synchronized (timerQueue) { 112 if (runing) { 113 //一开始执行一次 114 if (runnable.startAction) { 115 addTask(runnable); 116 } 117 timerQueue.add(runnable); 118 } else { 119 log.error("线程已经停止"); 120 } 121 } 122 } 123 124 // <editor-fold defaultstate="collapsed" desc="定时器线程执行器 public void timerRun()"> 125 /** 126 * 定时器线程执行器 127 */ 128 public void timerRun() { 129 ArrayList<TimerTaskEvent> taskModels; 130 synchronized (timerQueue) { 131 // 队列不为空的情况下 取出队列定时器任务 132 taskModels = new ArrayList<>(timerQueue); 133 } 134 if (!taskModels.isEmpty()) { 135 for (TimerTaskEvent timerEvent : taskModels) { 136 int execCount = timerEvent.getRunOther().getintValue("Execcount"); 137 long lastTime = timerEvent.getRunOther().getlongValue("LastExecTime"); 138 long nowTime = System.currentTimeMillis(); 139 if (lastTime == 0) { 140 timerEvent.getRunOther().put("LastExecTime", nowTime); 141 } else if (timerEvent.isCancel()) { 142 //如果任务已经取消 143 synchronized (timerQueue) { 144 timerQueue.remove(timerEvent); 145 } 146 log.debug("清理定时器任务:" + timerEvent.getClass().getName()); 147 } else if (nowTime > timerEvent.getStartTime() // 是否满足开始时间 148 && (nowTime - timerEvent.getSubmitTime() > timerEvent 149 .getIntervalTime())// 提交以后是否满足了间隔时间 150 && (timerEvent.getEndTime() <= 0 || nowTime < timerEvent 151 .getEndTime()) // 判断结束时间 152 && (nowTime - lastTime >= timerEvent 153 .getIntervalTime())) // 判断上次执行到目前是否满足间隔时间 154 { 155 // 提交执行定时器最先执行 156 this.addTask(timerEvent); 157 // 记录 158 execCount++; 159 timerEvent.getRunOther().put("Execcount", execCount); 160 timerEvent.getRunOther().put("LastExecTime", nowTime); 161 nowTime = System.currentTimeMillis(); 162 // 判断删除条件 163 if ((timerEvent.getEndTime() > 0 && nowTime < timerEvent.getEndTime()) 164 || (timerEvent.getActionCount() > 0 && timerEvent.getActionCount() <= execCount)) { 165 synchronized (timerQueue) { 166 timerQueue.remove(timerEvent); 167 } 168 log.debug("清理定时器任务:" + timerEvent.getClass().getName()); 169 } 170 } 171 } 172 } 173 } 174 // </editor-fold> 175 176 // <editor-fold defaultstate="collapsed" desc="查看线程堆栈 public void showStackTrace()"> 177 /** 178 * 179 * 查看线程堆栈 180 */ 181 public void showStackTrace() { 182 StringBuilder buf = new StringBuilder(); 183 for (MyThread currentThread : threads) { 184 long procc = System.currentTimeMillis() - currentThread.getLastExecuteTime(); 185 if (procc > 5 * 1000 && procc < 864000000L) {//小于10天//因为多线程操作时间可能不准确 186 buf.append("线程[") 187 .append(currentThread.getName()) 188 .append("]可能已卡死 -> ") 189 .append(procc / 1000f) 190 .append("s\n ") 191 .append("执行任务:") 192 .append(currentThread.getLastCommand().getClass().getName()); 193 try { 194 StackTraceElement[] elements = currentThread.getStackTrace(); 195 for (int i = 0; i < elements.length; i++) { 196 buf.append("\n ") 197 .append(elements[i].getClassName()) 198 .append(".") 199 .append(elements[i].getMethodName()) 200 .append("(").append(elements[i].getFileName()) 201 .append(";") 202 .append(elements[i].getLineNumber()).append(")"); 203 } 204 } catch (Exception e) { 205 buf.append(e); 206 } 207 buf.append("\n++++++++++++++++++++++++++++++++++"); 208 } 209 } 210 String toString = buf.toString(); 211 if (!StringUtil.isNullOrEmpty(toString)) { 212 log.error(toString); 213 if (System.currentTimeMillis() - lastSendMail > 5 * 60 * 1000) { 214 lastSendMail = System.currentTimeMillis(); 215 MailUtil.sendMail("线程执行已卡死 -> 游戏id-" + ObjectGlobal.GameID + " 平台-" + ObjectGlobal.Platform + " 服务器id-" + ObjectGlobal.ServerID, toString); 216 } 217 } 218 } 219 // </editor-fold> 220 221 @Override 222 public void run() { 223 MyThread currentThread = (MyThread) Thread.currentThread(); 224 while (runing) { 225 while (taskQueue.isEmpty() && runing) { 226 try { 227 /* 任务队列为空,则等待有新任务加入从而被唤醒 */ 228 synchronized (taskQueue) { 229 taskQueue.wait(500); 230 } 231 } catch (InterruptedException ie) { 232 log.error(ie); 233 } 234 } 235 /* 取出任务执行 */ 236 if (runing) { 237 currentThread.lastCommand = null; 238 currentThread.lastCommand = taskQueue.poll(); 239 } 240 if (currentThread.lastCommand != null) { 241 if (currentThread.lastCommand.isCancel()) { 242 //如果任务已经取消 243 continue; 244 } 245 /* 执行任务 */ 246 // r.setSubmitTimeL(); 247 currentThread.lastExecuteTime = System.currentTimeMillis(); 248 try { 249 currentThread.lastCommand.run(); 250 } catch (Exception e) { 251 log.error("工人<“" + currentThread.getName() + "”> 执行任务<" + currentThread.lastCommand.getClass().getName() + "> 遇到错误: ", e); 252 } 253 long timeL1 = System.currentTimeMillis() - currentThread.lastExecuteTime; 254 if (timeL1 <= 20) { 255 256 } else if (timeL1 <= 100L) { 257 log.info("工人<“" + currentThread.getName() + "”> 完成了任务:" + currentThread.lastCommand.toString() + " 执行耗时:" + timeL1); 258 } else if (timeL1 <= 200L) { 259 log.info("工人<“" + currentThread.getName() + "”> 长时间执行 完成任务:" + currentThread.lastCommand.toString() + " “考虑”任务脚本逻辑 耗时:" + timeL1); 260 } else { 261 log.info("工人<“" + currentThread.getName() + "”> 超长时间执行完成 任务:" + currentThread.lastCommand.toString() + " “考虑是否应该删除”任务脚本 耗时:" + timeL1); 262 } 263 currentThread.lastExecuteTime = 0; 264 } 265 } 266 log.error("线程结束, 工人<“" + Thread.currentThread().getName() + "”>退出"); 267 } 268 269 /** 270 * 自定义线程 271 */ 272 public class MyThread extends Thread { 273 274 /** 275 * 276 * @param tid 自定义线程id 277 * @param group 分组 278 * @param run 执行方法 279 * @param name 线程名称 280 */ 281 public MyThread(long tid, ThreadGroup group, Runnable run, String name) { 282 super(group, run, name); 283 this._id = tid; 284 } 285 286 //线程的自定义id 287 public long _id; 288 //正在执行的任务 289 public volatile TaskEvent lastCommand; 290 //开始执行任务的时间 291 public volatile long lastExecuteTime = 0; 292 293 public TaskEvent getLastCommand() { 294 return lastCommand; 295 } 296 297 public long getLastExecuteTime() { 298 return lastExecuteTime; 299 } 300 301 /** 302 * 返回线程自定义id 303 * 304 * @return 305 */ 306 @Override 307 public long getId() { 308 return _id; 309 } 310 311 } 312 313 /** 314 * 停止线程,设置线程的停止状态,并不会马上终止线程 315 */ 316 public void stop() { 317 this.runing = false; 318 } 319 320 public boolean isRuning() { 321 return runing; 322 } 323 324 @Override 325 public String toString() { 326 return "Thread{" + "tid=" + tid + ",Name=" + this.getName() + '}'; 327 } 328 329 }
我从 ThreadModel 构造函数的
1 public ThreadModel(ThreadGroup group, String name, int threadCount, Runnable runnable) { 2 synchronized (SYN_OBJECT) { 3 threadID++; 4 tid = threadID; 5 } 6 for (int i = 1; i <= threadCount; i++) { 7 MyThread thread; 8 if (runnable == null) { 9 thread = new MyThread(tid, group, this, name + "-" + tid + "-" + i); 10 } else { 11 thread = new MyThread(tid, group, runnable, name + "-" + tid + "-" + i); 12 } 13 thread.start(); 14 threads.add(thread); 15 } 16 this.name = name; 17 }
可以看出,这里我运行声明一个或者多个 MyThread 线程类
为什么要这样考虑呢打个比方,如果是处理日志的写入数据这种,没有共享数据,没有线程临界区的处理流程,我可以考虑使用N个线程去处理这样的工作;不会产生脏数据;
如果是想组队请求,技能施法这种处理,我需要单队列处理,那么threadmodel里面肯定只有一个MyThread 这样不算阻塞模式串行执行(或队列执行)把共享数据和线程临界区的问题也解决了不再依赖锁;
字很丑,请见谅
上面图片看出,在每一个threadmodel 里面都会两个队列,一个timertaskevent,一个是taskevent,会存在一个全局的timer thread;
全局的 timer thread 的作用是用来定时去处理和发现 threadmodel里面timertaskevent需要执行了,就把他加入到taskevent队里里面;最终执行是taskevent队列
timertaskevent为什么要存储在对应的threadmodel里面呢,那是因为比如,我A线程(threadmodel实例)运行一段时间后需要关闭,释放资源了,那么我还要去其他地方查找对应的timertask并移除掉;
1 package net.sz.engine.thread; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 /** 7 * 8 * <br> 9 * author 失足程序员<br> 10 * mail 492794628@qq.com<br> 11 * phone 13882122019<br> 12 */ 13 class TimerThread extends Thread { 14 15 private static final Object SYN_OBJECT = new Object(); 16 17 public TimerThread() { 18 super(ThreadPool.GloblThreadGroup, "Global Timer Thread"); 19 } 20 21 @Override 22 public void run() { 23 while (true) { 24 synchronized (SYN_OBJECT) { 25 try { 26 SYN_OBJECT.wait(2); 27 } catch (InterruptedException ex) { 28 } 29 } 30 HashMap<Long, ThreadModel> hashMap = new HashMap<>(ThreadPool.getThreadMap()); 31 for (Map.Entry<Long, ThreadModel> entrySet : hashMap.entrySet()) { 32 Long key = entrySet.getKey(); 33 ThreadModel value = entrySet.getValue(); 34 value.timerRun(); 35 } 36 } 37 } 38 39 }
线程模型的管理器
1 package net.sz.engine.thread; 2 3 import java.util.HashMap; 4 import java.util.concurrent.ConcurrentHashMap; 5 import net.sz.engine.script.manager.ScriptManager; 6 import net.sz.engine.timer.GlobTimerEvent; 7 import net.sz.engine.timer.PrintlnServerMemoryTimerEvent; 8 import org.apache.log4j.Logger; 9 10 /** 11 * 线程管理器 12 * 13 * <br> 14 * author 失足程序员<br> 15 * mail 492794628@qq.com<br> 16 * phone 13882122019<br> 17 */ 18 public class ThreadPool { 19 20 static private final Logger log = Logger.getLogger(ThreadPool.class); 21 static public final long GloblThread; 22 static private final TimerThread GloblTimerThread; 23 static final long CheckThreadTimerThreadModel; 24 static public final ThreadGroup GloblThreadGroup = new ThreadGroup("Global ThreadGroup"); 25 static public final ThreadGroup UnknownThreadGroup = new ThreadGroup(GloblThreadGroup, "Unknown ThreadGroup"); 26 static private final ConcurrentHashMap<Long, ThreadModel> threadMap = new ConcurrentHashMap<>(); 27 28 public static void main(String[] args) { 29 30 ThreadPool.addTimerTask(GloblThread, new TimerTaskEvent(1000) { 31 32 @Override 33 public void run() { 34 35 log.error("ssssss"); 36 } 37 }); 38 } 39 40 static { 41 //创建全局线程 42 GloblThread = addThreadModel(GloblThreadGroup, "GloblThread"); 43 //执行指定任务定时触发脚步 44 addTimerTask(GloblThread, new GlobTimerEvent(ScriptManager.getInstance().getBaseScriptEntry())); 45 //查询服务器消耗定时模型 46 addTimerTask(GloblThread, new PrintlnServerMemoryTimerEvent()); 47 //创建定时器线程 48 GloblTimerThread = new TimerThread(); 49 GloblTimerThread.start(); 50 //检查线程卡死情况 51 CheckThreadTimerThreadModel = addThreadModel(GloblThreadGroup, "Check Thread Timer Event"); 52 addTimerTask(CheckThreadTimerThreadModel, new CheckThreadTimerEvent()); 53 } 54 55 /** 56 * 删除指定id线程模型的时候回设置状态为停止状态 57 * 58 * @param tid 59 * @return 60 */ 61 static public ThreadModel remove(long tid) { 62 ThreadModel remove = threadMap.remove(tid); 63 if (remove != null) { 64 remove.stop(); 65 } 66 return remove; 67 } 68 69 /** 70 * 获取线程池中所有线程 71 * 72 * @return 73 */ 74 static public ConcurrentHashMap<Long, ThreadModel> getThreadMap() { 75 return threadMap; 76 } 77 78 /** 79 * 获取线程池的一个线程 80 * 81 * @param threadId 82 * @return 83 */ 84 static public ThreadModel getThreadModel(long threadId) { 85 ThreadModel get = threadMap.get(threadId); 86 if (get == null) { 87 log.error("无法找到线程模型:" + threadId, new Exception("无法找到线程模型:" + threadId)); 88 } 89 return get; 90 } 91 92 /** 93 * 向线程池注册一个线程 94 * <br> 95 * 默认分组 UnknownThreadGroup 96 * 97 * @param name 线程名称 98 * @return 99 */ 100 static public long addThreadModel(String name) { 101 return addThreadModel(UnknownThreadGroup, name); 102 } 103 104 /** 105 * 向线程池注册一个线程 106 * <br> 107 * 默认分组 UnknownThreadGroup 108 * 109 * @param name 线程名称 110 * @param threadcount 线程量 111 * @return 112 */ 113 static public long addThreadModel(String name, int threadcount) { 114 return addThreadModel(UnknownThreadGroup, name, threadcount); 115 } 116 117 /** 118 * 向线程池注册一个线程 119 * 120 * @param group 线程分组信息 121 * @param name 线程名称 122 * @return 123 */ 124 static public long addThreadModel(ThreadGroup group, String name) { 125 return addThreadModel(group, name, 1); 126 } 127 128 /** 129 * 向线程池注册一个线程 130 * 131 * @param group 线程分组信息 132 * @param name 线程名称 133 * @param threadcount 线程量 134 * @return 135 */ 136 static public long addThreadModel(ThreadGroup group, String name, int threadcount) { 137 return addThreadModel(group, name, null, threadcount); 138 } 139 140 /** 141 * 向线程池注册一个线程 142 * 143 * @param group 线程分组信息 144 * @param name 线程名称 145 * @param runnable 146 * @param threadcount 线程量 147 * @return 148 */ 149 static public long addThreadModel(ThreadGroup group, String name, Runnable runnable, int threadcount) { 150 ThreadModel threadModel = new ThreadModel(group, name, threadcount, runnable); 151 return addThreadModel(threadModel); 152 } 153 154 /** 155 * 向线程池注册一个线程 156 * 157 * @param threadModel 158 */ 159 static public long addThreadModel(ThreadModel threadModel) { 160 threadMap.put(threadModel.getId(), threadModel); 161 return threadModel.getId(); 162 } 163 164 /** 165 * 添加任务 166 * 167 * @param threadId 168 * @param task 169 * @return 170 */ 171 static public boolean addTask(long threadId, TaskEvent task) { 172 ThreadModel threadModel = getThreadModel(threadId); 173 if (threadModel != null) { 174 threadModel.addTask(task); 175 return true; 176 } 177 return false; 178 } 179 180 /** 181 * 添加定时器任务 182 * 183 * @param threadId 184 * @param task 185 * @return 186 */ 187 static public boolean addTimerTask(long threadId, TimerTaskEvent task) { 188 ThreadModel threadModel = getThreadModel(threadId); 189 if (threadModel != null) { 190 threadModel.addTimer(task); 191 return true; 192 } 193 return false; 194 } 195 196 /** 197 * 添加任务,添加任务到当前线程 198 * 199 * @param task 200 * @return 201 */ 202 static public boolean addCurrentThreadTask(TaskEvent task) { 203 Thread currentThread = Thread.currentThread(); 204 if (currentThread instanceof ThreadModel.MyThread) { 205 long threadId = currentThread.getId(); 206 ThreadModel threadModel = getThreadModel(threadId); 207 if (threadModel != null) { 208 threadModel.addTask(task); 209 return true; 210 } 211 } 212 return false; 213 } 214 215 /** 216 * 添加定时器任务,添加任务到当前线程 217 * 218 * @param task 219 * @return 220 */ 221 static public boolean addCurrentThreadTimerTask(TimerTaskEvent task) { 222 Thread currentThread = Thread.currentThread(); 223 if (currentThread instanceof ThreadModel.MyThread) { 224 long threadId = currentThread.getId(); 225 ThreadModel threadModel = getThreadModel(threadId); 226 if (threadModel != null) { 227 threadModel.addTimer(task); 228 return true; 229 } 230 } 231 return false; 232 } 233 }
接下来我们看看使用情况
上篇文章中线程介绍代码
1 public static void main(String[] args) throws InterruptedException { 2 //线程并行情况,有多个线程执行多个任务/函数 3 new Thread(new Run1()).start(); 4 new Thread(new Run2()).start(); 5 } 6 7 //任务1 8 static class Run1 implements Runnable { 9 10 @Override 11 public void run() { 12 //执行任务1 13 run1(); 14 //执行任务3 15 run3(); 16 } 17 } 18 //任务2 19 20 static class Run2 implements Runnable { 21 22 @Override 23 public void run() { 24 //执行任务3 25 run3(); 26 //执行任务1 27 run1(); 28 //执行任务2 29 run2(); 30 } 31 } 32 33 //任务1 34 public static void run1() { 35 System.out.println("run1()->" + System.currentTimeMillis()); 36 } 37 38 //任务2 39 public static void run2() { 40 System.out.println("run2()->" + System.currentTimeMillis()); 41 } 42 43 //任务3 44 public static void run3() { 45 System.out.println("run3()->" + System.currentTimeMillis()); 46 }
我把代码切换模式
1 public static void main(String[] args) throws InterruptedException { 2 //线程并行情况,有多个线程执行多个任务/函数 3 4 long test1 = ThreadPool.addThreadModel("测试线程-1"); 5 long test2 = ThreadPool.addThreadModel("测试线程-2"); 6 //添加任务 7 ThreadPool.addTask(test1, new Run1()); 8 ThreadPool.addTask(test2, new Run2()); 9 //添加定时器任务 10 ThreadPool.addTimerTask(test1, new TimerRun1()); 11 ThreadPool.addTimerTask(test2, new TimerRun2()); 12 13 } 14 15 //任务1 16 static class Run1 extends TaskEvent { 17 18 @Override 19 public void run() { 20 //执行任务1 21 run1(); 22 //执行任务3 23 run3(); 24 } 25 } 26 27 //任务1 28 static class TimerRun1 extends TimerTaskEvent { 29 30 public TimerRun1() { 31 super(500);//500毫秒无限制执行 32 } 33 34 @Override 35 public void run() { 36 //执行任务1 37 run1(); 38 //执行任务3 39 run3(); 40 } 41 } 42 43 //任务2 44 static class Run2 extends TaskEvent { 45 46 @Override 47 public void run() { 48 //执行任务3 49 run3(); 50 //执行任务1 51 run1(); 52 //执行任务2 53 run2(); 54 } 55 } 56 57 //任务2 58 static class TimerRun2 extends TimerTaskEvent { 59 60 public TimerRun2() { 61 super(500);//500毫秒无限制执行 62 } 63 64 @Override 65 public void run() { 66 //执行任务3 67 run3(); 68 //执行任务1 69 run1(); 70 //执行任务2 71 run2(); 72 } 73 } 74 75 //任务1 76 public static void run1() { 77 System.out.println("run1()->" + System.currentTimeMillis()); 78 } 79 80 //任务2 81 public static void run2() { 82 System.out.println("run2()->" + System.currentTimeMillis()); 83 } 84 85 //任务3 86 public static void run3() { 87 System.out.println("run3()->" + System.currentTimeMillis()); 88 }
接下来我们看看执行效果
run1()->1472120543013
run3()->1472120543013
run3()->1472120543017
run1()->1472120543017
run2()->1472120543017
run1()->1472120543517
run3()->1472120543517
run3()->1472120543517
run1()->1472120543517
run2()->1472120543517
run1()->1472120544018
run3()->1472120544018
run3()->1472120544018
run1()->1472120544018
run2()->1472120544018
run1()->1472120544520
run3()->1472120544520
run3()->1472120544520
run1()->1472120544520
run2()->1472120544520
run1()->1472120545021
run3()->1472120545021
run3()->1472120545021
run1()->1472120545021
run2()->1472120545021
run1()->1472120545521
run3()->1472120545521
一切正常;
这就是我的自定义线程模型;
到这里我的自定义线程模型就算介绍完成了;
那么优缺点在哪里呢?
优点是,数据流程控制很清晰,包括现在执行情况,以及线程卡死监控和任务 的定时器执行;
缺点,这个自定义线程模型依然不可能解决线程数据安全和临界区问题,在适当的时候依然需要靠锁或者其他形式来解决;
不足之处希望大神们指出,我好即时纠正。
跪求保留标示符 /** * @author: Troy.Chen(失足程序员, 15388152619) * @version: 2021-07-20 10:55 **/ C#版本代码 vs2010及以上工具可以 java 开发工具是netbeans 和 idea 版本,只有项目导入如果出现异常,请根据自己的工具调整 提供免费仓储。 最新的代码地址:↓↓↓ https://gitee.com/wuxindao 觉得我还可以,打赏一下吧,你的肯定是我努力的最大动力