ผู้ที่อ่านบทความก่อนหน้าของฉันอาจรู้ว่าฉันกำลังพัฒนาเกม ความคิดและจุดเริ่มต้นของฉันหลายอย่างได้รับการจัดการตามแนวคิดเกมดังนั้นอาจมีความขัดแย้งกับเว็บและไม่สอดคล้องกับมัน
ให้ฉันบอกคุณว่าทำไมฉันถึงต้องการปรับแต่งโมเดลเธรด?
ตามเกม MMORPG หรือ MMORPG ที่ฉันทำเธรดจะแบ่งออกเป็นเธรดหลักเธรดการซิงโครไนซ์ทั่วโลกเธรดแชทเธรดทีมเธรดแผนที่และการแจกแจงข้อความแผนที่และเธรดการส่งมอบ ฯลฯ
บางคอลัมน์จำเป็นต้องควบคุมตามการแบ่งและการไหลของข้อมูลของฉัน
สิ่งสำคัญที่ต้องทำในเกมเซิร์ฟเวอร์คือการยอมรับคำขอคำสั่งของผู้เล่น -> การดำเนินการที่เกี่ยวข้อง -> ส่งคืนผลลัพธ์;
ข้อความทั้งหมดบนฝั่งเซิร์ฟเวอร์จะลงทะเบียนในตัวจัดการข้อความจากนั้นจะระบุโมเดลเธรดเมื่อลงทะเบียนข้อความ
หากจำเป็นต้องส่งข้อความไปยังเธรดแผนที่ของผู้เล่นสำหรับการประมวลผลเมื่อลงทะเบียนข้อความคุณต้องใช้โมเดลเธรด (แผนที่การแจกแจงข้อความและเธรดส่ง)
มาวิเคราะห์แบบจำลองเธรดก่อน
ก่อนที่จะดูรหัสโมเดลเธรดฉันดูโมเดลงานของฉันก่อน
แพ็คเกจ net.sz.engine.thread; นำเข้า java.io.serializable; นำเข้า org.apache.log4j.logger; นำเข้า net.sz.engine.structs.objectattribute; นำเข้า net.sz.engine.structs.objectglobal;/** 13882122019 <br> */Public Abstract Class TaskEvent ใช้งาน serializable, cloneable {logger สุดท้ายคงที่ logger log = logger.getLogger (taskEvent.class); ส่วนตัวคงที่สุดท้าย Long Serialversionuid = 4196020659994845804L; // runtime data private transient final objectattribute runother = new ObjectAttribute; // การสร้างงานเวลาป้องกันการสร้างเวลานาน; // งานที่ไม่ซ้ำกัน ID ได้รับการปกป้อง Long TaskId; // การยกเลิกงานที่ได้รับการป้องกันบูลีนยกเลิก = false; งานสาธารณะ {this.runother.put ("submittime", system.currenttimemillis); createTime = system.currentTimeMillis; ยกเลิก = false; taskId = objectGlobal.getUUID; } สาธารณะยาว getCreateTime {return createTime; } โมฆะสาธารณะ setCreateTime (long createTime) {this.createTime = createTime; } สาธารณะ Long GetSubMittime {ส่งคืนสิ่งนี้ runother.getLongValue ("submittime"); } Public ObjectAttribute getRunother {return runother; } บูลีนสาธารณะ iscancel {return cancel; } โมฆะสาธารณะ setCancel (บูลีนยกเลิก) {this.cancel = ยกเลิก; } public abstract void run; @Override วัตถุสาธารณะโคลนโยน clonenotsupportedException {return super.clone; // หากต้องการเปลี่ยนวิธีการที่สร้างขึ้นให้เลือกเครื่องมือ | เทมเพลต -แพ็คเกจ net.sz.engine.thread;/** * ตัวจับเวลาผู้ดำเนินการ * * <br> * ผู้เขียนโปรแกรมเมอร์ล้มเหลว <br> * จดหมาย [email protected] <br> * โทรศัพท์ 13882122019 <br> */บทคัดย่อระดับสาธารณะ / *** เวลาในการเริ่มต้นการดำเนินการ*/ ป้องกันเวลาเริ่มต้นมานาน; / *** ว่าจะดำเนินการหนึ่งครั้งที่จุดเริ่มต้น*/ boolean startaction ที่ได้รับการป้องกันหรือไม่ / *** เวลาสิ้นสุด*/ ได้รับการป้องกันสุดท้ายเวลานาน; / *** จำนวนการประหารชีวิต*/ การป้องกัน int actionCount; / *** เวลาดำเนินการช่วงเวลา*/ ช่วงเวลาที่ได้รับการป้องกัน / **** @param starttime ระบุเวลาเริ่มต้น* @param iSstartaction ไม่ว่าจะดำเนินการหนึ่งครั้งในตอนเริ่มต้น* @param endtime ระบุเวลาสิ้นสุด* @param actioncount ระบุจำนวนการประหารชีวิต* @param Intervaltime ระบุช่วงเวลาที่น่าสนใจ this.starttime = starttime; this.tartaction = iSstartaction; this.endtime = endtime; this.actionCount = ActionCount; this.intervaltime = IntervalTime; } / *** ระบุเวลาดำเนินการเริ่มต้นของงาน** @param starttime ระบุเวลาเริ่มต้น* @param iSstartaction ไม่ว่าจะดำเนินการครั้งเดียวที่จุดเริ่มต้น* @param actionCount ระบุจำนวนการประหาร ActionCount, IntervalTime); } / *** เวลาสิ้นสุดที่ระบุคือเวลาสิ้นสุดและจำนวนการดำเนินการไม่จำเป็นต้องเพียงพอ** @param iSstartaction ว่าจะดำเนินการหนึ่งครั้งที่จุดเริ่มต้น* @param endtime ระบุเวลาสิ้นสุด* @param actionCount ระบุจำนวนการดำเนินการ* @param IntervalTime สิ่งนี้ (0, istartaction, endtime, actionCount, IntervalTime); } / *** ระบุเวลาเริ่มต้นและเวลาสิ้นสุด** @param starttime ระบุเวลาเริ่มต้น* @param Endtime ระบุเวลาสิ้นสุด* @param Intervaltime ระบุช่วงเวลาช่วงเวลา* / TimerTaskEvent สาธารณะนาน } / *** เวลาดำเนินการที่ระบุและเวลาช่วงเวลา** @param actionCount ระบุจำนวนการประหารชีวิต* @param Intervaltime ระบุเวลาช่วงเวลา* / Public TimerTaskEvent (int actionCount, IntervalTime int) {สิ่งนี้ (0, เท็จ, 0, ActionCount, IntervalTime); } / *** การดำเนินการไม่ จำกัด หลังจากการส่ง* @param IntervalTime เวลาที่ระบุเวลาช่วงเวลา* / Public TimerTaskEvent (ช่วงเวลา int) {this (0, false, 0, -1, IntervalTime); } Public Long GetStartTime {return starttime; } โมฆะสาธารณะ setStartTime (starttime ยาว) {this.starttime = starttime; } บูลีนสาธารณะ iSstartaction {return startAction; } โมฆะสาธารณะ setStartaction (boolean startaction) {this.startaction = startAction; } public long getEndTime {return endtime; } โมฆะสาธารณะ setEntTime (endtime ยาว) {this.endtime = endtime; } public int getActionCount {return actionCount; } โมฆะสาธารณะ setActionCount (int actionCount) {this.ActionCount = ActionCount; } public int getIntervaltime {return IntervalTime; } โมฆะสาธารณะ setIntervalTime (intvaltime int) {this.intervaltime = IntervalTime; -
นี่คือโมเดลงานและโมเดลงานจับเวลา
แพ็คเกจ net.sz.engine.thread; นำเข้า java.util.arraylist; นำเข้า java.util.list; นำเข้า java.util.concurrent.concurrentlinkedqueue; นำเข้า net.sz.engine.structs.objectglobal; org.apache.log4j.logger; นำเข้า org.jboss.jandex.main;/** * โมเดลเธรด * <br> * ผู้เขียนโปรแกรมเมอร์ล้มเหลว <br> * จดหมาย [email protected] <br> * โทรศัพท์ 13882122019 <br> * logger.getLogger (threadmodel.class); ด้ายยาวคงที่ส่วนตัว = 0; วัตถุสุดท้ายที่ได้รับการป้องกัน syn_object = วัตถุใหม่; ได้รับการปกป้อง TID ยาว; ชื่อสตริงที่ได้รับการป้องกัน ได้รับการป้องกัน Long LastSendMail = 0; ได้รับการปกป้อง arraylist สุดท้าย <MyThread> threads = new ArrayList <>; /*** รายการงานรายการงานที่ปลอดภัยสำหรับเธรด* // // รายการสุดท้ายที่ได้รับการป้องกัน <SaskModel> taskQueue = new ArrayList <>; ได้รับการป้องกันขั้นสุดท้ายพร้อมกัน linkedqueue <taskEvent> taskqueue = ใหม่พร้อมกันพร้อมกันกับการเชื่อมโยงกัน <>; / ***/ รายการสุดท้ายที่ได้รับการป้องกัน <TimerTaskEvent> timerqueue = new ArrayList <>; // ตัวตนที่ผิดพลาดการลบเธรดบูลีนระเหยที่มีการป้องกันการทำงาน = true; Public ThreadModel (กลุ่ม ThreadGroup) {นี้ (กลุ่ม, "ไม่มีชื่อ", 1); } public ThreadModel (ชื่อสตริง) {this (threadpool.unknownthreadgroup, ชื่อ, 1); } Public ThreadModel (กลุ่ม ThreadGroup, ชื่อสตริง, int ThreadCount) {this (กลุ่ม, ชื่อ, ThreadCount, NULL); } Public ThreadModel (กลุ่ม ThreadGroup, ชื่อสตริง, int ThreadCount, runnable runnable) {ซิงโครไนซ์ (syn_object) {threadId ++; tid = threadId; } สำหรับ (int i = 1; i <= threadCount; i ++) {เธรด MyThread; ถ้า (runnable == null) {เธรด = ใหม่ mythread (tid, กลุ่ม, นี่คือชื่อ + "-" + tid + "-" + i); } thread.start; Threads.add (เธรด); } this.name = name; } / ** * ชื่อเธรด * * @return * / สตริงสาธารณะ getName {return name; } / ** * รับ ID ที่กำหนดเองของเธรด * * @return * / Public Long getId {return this.tid; } / ** * เพิ่มงานใหม่สำหรับงานใหม่แต่ละงานคิวงานจะต้องตื่นขึ้น * * @param runnable * / โมฆะสาธารณะ addtask (taskEvent runnable) {taskqueue.add (runnable); ซิงโครไนซ์ (taskqueue) {/ * ปลุกคิวและเริ่มดำเนินการ */ taskqueue.notifyall; }}/** * เพิ่มงานตัวจับเวลาลงในเธรด * * @param runnable */โมฆะสาธารณะ addtimer (timertaskevent runnable) {ซิงโครไนซ์ (timerqueue) {ถ้า (runing) {// ดำเนินการหนึ่งครั้งที่จุดเริ่มต้นถ้า } timerqueue.add (runnable);} else {log.error ("เธรดหยุด"); }}}} // <editor-fold defaultState = "ยุบ" desc = "timer thread executor สาธารณะโมฆะ public timerrun"> / *** thread thread executor* / โมฆะสาธารณะ timerrun {arraylist <Timertaskevent> taskmodels; ซิงโครไนซ์ (timerqueue) {// ถ้าคิวไม่ว่างเปล่าให้ใช้งานคิวจับเวลา taskModels = arrayList ใหม่ <> (timerqueue); } if (! taskModels.isEmpty) {สำหรับ (TimerTaskEvent TimerEvent: TaskModels) {int execount = timeReVent.getRunother.getTinValue ("Execount"); LINATE LISTTIME = TIMEREVENT.GETRUNOTHER.GETLONGVALUE ("LastExectime"); นานแล้ว = System.currentTimeMillis; if (ล่าสุด == 0) {timeRevent.getRunother.put ("LastExectime", ตอนนี้);} อื่นถ้า (timerEvent.iscancel) {// ถ้างานถูกยกเลิกการซิงโครไนซ์ (timerqueue) } log.debug ("ทำความสะอาดงานตัวจับเวลา:" + timerEvent.getClass.getName);} ถ้า (ตอนนี้> timeRevent.getStartTime // ไม่ว่าจะเป็นเวลาเริ่มต้นหรือไม่ TimerEvent.getEndTime) // กำหนดเวลาสิ้นสุด && (ตอนนี้ - เวลาสุดท้าย> = timerEvent.getIntervalTime)) // พิจารณาว่าช่วงเวลานั้นได้รับความพึงพอใจตั้งแต่การดำเนินการครั้งล่าสุด {// ตัวจับเวลาการส่งการส่งเป็นครั้งแรก execcount); timeRevent.getRunother.put ("lastExectime" ตอนนี้); nowtime = system.currentTimemillis; // กำหนดเงื่อนไขการลบถ้า ((timeRevent.getEntime> 0 && nowtime <TimeRevent.getEntEntTime) || (timerqueue) {timerqueue.remove (timerEvent); } log.debug ("งานทำความสะอาดตัวจับเวลา:" + TimerEvent.getClass.getName); }}}}}}} // </editor-fold> // <editor-fold defaultState = "collapsed" desc = "ดูเธรดสแต็กโมฆะ public void showstacktrace">/**** ดูสแต็ก*/โมฆะสาธารณะ showstacktrace สำหรับ (MyThread CurrentThread: เธรด) {Long procc = system.currentTimeMillis - currentthread.getLastexecutetime; ถ้า (procc> 5 * 1000 && procc <86400000l) {// น้อยกว่า 10 วัน // stuck-> ") .append (procc/1000f) .append (" s/n ") .append (" ดำเนินการงาน: ") .append (currentthread.getLastCommand.getClass.getName); ลอง {stackTracelement Elements = currentThread.getStackTrace; .Append (องค์ประกอบ [i] .getClassName) .Append (".") .Append (องค์ประกอบ [i] .getMethodname) .append ("("). ผนวก (องค์ประกอบ [i] .getFilename) .append (";"). }} catch (exception e) {buf.append (e); } buf.append ("/n +++++++++++++++++++++++++++++++++++++++++ }} สตริง toString = buf.toString; if (! stringutil.isnullorempty (toString)) {log.error (toString); ถ้า (System.currentTimeMillis-LastSendMail> 5 * 60 * 1000) {LastSendMail = System.currentTimeMillis; mailutil.sendmail ( ObjectGlobal.platform + "เซิร์ฟเวอร์ ID-" + ObjectGlobal.serverid, ToString); }}} // </editor-fold> @Override โมฆะสาธารณะเรียกใช้ {MyThread currentThread = (MyThread) เธรด currentThread; ในขณะที่ (การรัน) {ในขณะที่ (taskqueue.isempty && การรัน) {ลอง {/* คิวงานว่างเปล่าจากนั้นงานใหม่กำลังรองานใหม่ที่จะเข้าร่วมและตื่นขึ้น*/ซิงโครไนซ์ (taskqueue) {taskqueue.wait (500); }} catch (interruptedException IE) {log.error (เช่น); }}/* ออกไปงานเพื่อเรียกใช้งาน*/if (runing) {currentthread.lastCommand = null; currentthread.lastCommand = taskqueue.poll; } if (currentthread.lastCommand! = null) {ถ้า (currentthread.lastCommand.iscancel) {// ถ้างานถูกยกเลิกดำเนินการต่อ; }/* ดำเนินการงาน* /// r.setsubmittimel; currentthread.lastexecutetime = system.currentTimeMillis; ลอง {currentThread.lastCommand.run;} catch (ยกเว้น e) {log.error ("คนงาน <" " "> พบข้อผิดพลาด:", e); } Long Timel1 = System.currentTimeMillis - currentthread.lastexecutetime; if (timel1 <= 20) {} else ถ้า (timel1 <= 100l) {log.info ("คนงาน <" " + currentthread.getName +" "> เสร็จสิ้นงาน:" + currentthread.lastCommand.toString + "timel.s (timel1 <= 200l) + ""> การดำเนินการในระยะยาวของการทำงานให้เสร็จ: " + currentthread.lastCommand.toString +" "พิจารณา" งานสคริปต์ลอจิกใช้เวลานาน: " + timel1);} else {log.info (" คนงาน <"" currentthread.getName + " ลบ "งานสคริปต์ที่ใช้เวลานาน:" + timel1); } currentThread.lastExecutetime = 0; }} log.error ("ปลายเธรด, Worker <" " + thread.currentthread.getName +" "> exit"); } / *** เธรดที่กำหนดเอง* / คลาสสาธารณะ MyThread ขยายเธรด { / **** @param tid thread custom id* @param กลุ่มกลุ่ม* @param run วิธีการดำเนินการ* @param ชื่อเธรดชื่อ* / Public Mythread (Long TID, กลุ่ม ThreadGroup, Runnable Run } // ID ที่กำหนดเองของเธรดสาธารณะยาว _id; // การดำเนินการงานที่มีความผันผวนสาธารณะ LastCommand; // ถึงเวลาที่จะเริ่มดำเนินการงานสาธารณะที่มีความผันผวนนาน LastExecuteTime = 0; Public TaskEvent GetLaStCommand {return LastCommand; } สาธารณะยาว getLaStExecuteTime {return lastExecutetime; } / ** * ส่งคืน ID Custom Custom * * @return * / @Override สาธารณะ Long getId {return _id; }} / *** หยุดเธรดตั้งค่าสถานะหยุดของเธรดและจะไม่ยุติเธรดทันที* / โมฆะสาธารณะหยุด {this.runing = false; } บูลีนสาธารณะ isruning {return running; } @Override สตริงสาธารณะ toString {return "เธรด {" + "tid =" + tid + ", name =" + this.getName + '}'; -
ฉันสร้างจาก Threadmodel
Public ThreadModel (กลุ่ม ThreadGroup, ชื่อสตริง, int ThreadCount, Runnable Runnable) {ซิงโครไนซ์ (syn_object) {threadId ++; tid = threadId; } สำหรับ (int i = 1; i <= threadCount; i ++) {เธรด MyThread; ถ้า (runnable == null) {เธรด = ใหม่ mythread (tid, กลุ่ม, นี่คือชื่อ + "-" + tid + "-" + i); } thread.start; Threads.add (เธรด); } this.name = name; -ดังที่เห็นได้ที่นี่ฉันเรียกใช้คลาสเธรด MyThread ประกาศ
ทำไมฉันถึงคิดถึงเรื่องนี้? ตัวอย่างเช่นหากฉันกำลังประมวลผลข้อมูลการเขียนบันทึกเช่นไม่มีข้อมูลที่ใช้ร่วมกันและไม่มีกระแสการประมวลผลพื้นที่สำคัญของเธรดฉันสามารถพิจารณาใช้เธรด N เพื่อประมวลผลงานดังกล่าว มันจะไม่สร้างข้อมูลที่สกปรก
หากฉันต้องการร่วมมือกันและขอทักษะการคัดเลือกนักแสดงฉันต้องประมวลผลคิวเดียวแล้วจะต้องมีตำนานหนึ่งเรื่องใน ThreadModel สิ่งนี้ไม่ได้นับเป็นการบล็อกการดำเนินการแบบอนุกรม (หรือการดำเนินการคิว) เพื่อแก้ปัญหาการแบ่งปันข้อมูลและพื้นที่วิกฤตเธรดซึ่งไม่ได้ขึ้นอยู่กับล็อคอีกต่อไป
ฉันน่าเกลียดมากโปรดยกโทษให้ฉัน
ดังที่แสดงในภาพด้านบนจะมีสองคิวในแต่ละ Threadmodel หนึ่ง timetaskevent และ taskvent อื่น ๆ และจะมีเธรดตัวจับเวลาทั่วโลก
ฟังก์ชั่นของเธรดตัวจับเวลาทั่วโลกคือการประมวลผลและพบว่า timetaskevent ใน ThreadModel จำเป็นต้องดำเนินการดังนั้นจึงถูกเพิ่มเข้าไปในทีมงาน TaskVent; การดำเนินการขั้นสุดท้ายคือคิวงาน TaskVent
ทำไม TimetaskEvent ควรเก็บไว้ใน ThreadModel ที่สอดคล้องกัน? นั่นเป็นเพราะตัวอย่างเช่นหลังจากเธรดของฉัน (Instance Threadmodel) ทำงานเป็นระยะเวลาหนึ่งฉันต้องปิดและให้ทรัพยากรฟรีดังนั้นฉันต้องไปที่อื่น ๆ เพื่อค้นหา timetask ที่เกี่ยวข้องและลบออก;
แพ็คเกจ net.sz.engine.thread; นำเข้า java.util.hashmap; นำเข้า java.util.map;/** * * <br> * ผู้แต่งโปรแกรมโปรแกรมเมอร์ที่ล้ม <br> * จดหมาย [email protected] <br> * โทรศัพท์ 13882122019 <br> Public TimerThread {super (threadpool.globeblthreadgroup, "Global Timer Thread"); } @Override โมฆะสาธารณะเรียกใช้ {ในขณะที่ (จริง) {ซิงโครไนซ์ (syn_object) {ลอง {syn_object.wait (2);} catch (interruptedException ex) {}} hashmap <long, threadmodel> hashmap = new hashmap < hashmap.entryset) {long key = entryset.getKey; threadModel value = entrySet.getValue; Value.timerrun; -
ตัวจัดการรุ่นเธรด
แพ็คเกจ net.sz.engine.thread; นำเข้า java.util.hashmap; นำเข้า java.util.concurrent.concurrenthashmap; นำเข้า net.sz.engine.script.manager.scriptManager; นำเข้า net.sz.engine.timer.globtimerevent; org.apache.log4j.logger;/** * ผู้จัดการเธรด * * <br> * ผู้เขียนโปรแกรมเมอร์ล้มเหลว <br> * จดหมาย [email protected] <br> * โทรศัพท์ 13882122019 <br> */ชั้นเรียนสาธารณะ สาธารณะคงที่รอบสุดท้าย globblthread; แบบคงที่ส่วนตัวสุดท้าย TimerThreadGloblTimerThread; คงที่ครั้งสุดท้าย Long CheckThreadTimerThreadModel; public public สุดท้าย threadGroup globlThreadGroup = new ThreadGroup ("Global ThreadGroup"); public public สุดท้าย threadGroup unknownThreadGroup = ใหม่ ThreadingGroup (GloblTHreadGroup, "Unknown ThreadGroup"); แบบคงที่ส่วนตัวสุดท้ายพร้อมกันพร้อมกัน <long, ThreadModel> ThreadMap = ใหม่พร้อมกันพร้อมกัน <>; โมฆะสาธารณะคงที่หลัก (สตริง [] args) {threadpool.addtimertask (globlThread, timertaskevent ใหม่ (1,000) {@Overridepublic เป็นโมฆะเรียกใช้ {log.error ("SSSSS");}}); } คงที่ {// สร้างเธรด Global GloblThread = AddThreadModel (GloblThreadGroup, "globlThread"); // ดำเนินการกำหนดเวลางานที่ระบุเพื่อเรียกเสียงฝีเท้า addTimerTask (globlThread, globtimerevent ใหม่ (scriptManager.getInstance.getBasescriptentry)); // สอบถามรูปแบบการใช้เวลาการบริโภคเซิร์ฟเวอร์ addTimerTask (GloblThread, printlnserverMemoryTimerEvent ใหม่); // สร้างเธรดตัวจับเวลา globltimerThread = timerThread ใหม่; globltimerthread.start; // ตรวจสอบเธรด Stuck StuckthreadTimerThreadModel = AddThreadModel (GloblThreadGroup, "ตรวจสอบเหตุการณ์ ThreadTimer"); AddTimerTask (CheckThreadTimerThreadModel, ใหม่ CheckThreadTimerEvent); } / ** * เมื่อลบโมเดลเธรด ID ที่ระบุตั้งค่าสถานะเป็นสถานะหยุด * * @param tid * @return * / ด้ายสาธารณะแบบคงที่ลบ (ยาว tid) {threadmodel ลบ = threadmap.remove (tid); if (ลบ! = null) {remove.stop; } return remove; } / ** * รับเธรดทั้งหมดในพูลเธรด * * @return * / public public public concurrentHashMap <long, ThreadModel> getThreadMap {return ThreadMap; } / ** * รับเธรดในพูลเธรด * * @param ThreadId * @return * / Static Public ThreadModel GetThreadModel (Long ThreadId) {ThreadModel get = ThreadMap.get (ThreadId); ถ้า (get == null) {log.error ("ไม่พบโมเดลเธรด:" + threadId, ข้อยกเว้นใหม่ ("ไม่พบโมเดลเธรด:" + threadId)); } return get; } / ** * ลงทะเบียนเธรดไปยังพูลเธรด * <br> * การจัดกลุ่มเริ่มต้นไม่ทราบทุ่งอ่าน Group * * @param ชื่อเธรดชื่อ * @return * / สาธารณะคงที่ความยาว addThreadModel (ชื่อสตริง) {return addThreadModel } / ** * ลงทะเบียนเธรดไปยังพูลเธรด * <br> * การจัดกลุ่มเริ่มต้นไม่ทราบทุ่งหญ้า * * @param ชื่อ ThreadName * @param ThreadCount ThreadCount * @return * / public Long addThreadModel (ชื่อสตริง, int ThreadCount) } / *** ลงทะเบียนเธรดด้วยเธรดพูล** @param กลุ่มเธรดการจัดกลุ่มข้อมูล* @param ชื่อเธรดชื่อ* @return* / สาธารณะคงที่ความยาว addthreadModel (กลุ่ม ThreadGroup, ชื่อสตริง) {return addThreadModel (กลุ่ม, ชื่อ, 1); } / *** ลงทะเบียนเธรดด้วยพูลเธรด** @param กลุ่มเธรดการจัดกลุ่มข้อมูล* @param ชื่อ threadname* @param ThreadCount ThreadCount* @return* / public Public Long addThreadModel (กลุ่ม ThreadGroup, ชื่อสตริง, int ThreadCount) } / *** ลงทะเบียนเธรดด้วยพูลเธรด** @param กลุ่มข้อมูล ThreadGroup* @param ชื่อ threadname* @param runnable* @param ThreadCount ThreadCount* @return* / public long addThreadModel (threadgroup กลุ่ม, runnable runnable return addThreadModel (ThreadModel); } / ** * ลงทะเบียนเธรดด้วยพูลเธรด * * @param ThreadModel * / แบบคงที่สาธารณะยาว addThreadModel (ThreadModel ThreadModel) {ThreadMap.put (ThreadModel.getId, ThreadModel); ส่งคืน ThreadModel.getId; } / ** * เพิ่มงาน * * @param threadid * @param task * @return * / บูลีนสาธารณะแบบคงที่ addTask (ยาว threadId, taskEvent task) {ThreadModel ThreadModel = getThreadModel (ThreadId); if (threadmodel! = null) {threadmodel.addtask (task); return true; } return false; } / ** * เพิ่มงานตัวจับเวลา * * @param threadid * @param task * @return * / บูลีนสาธารณะแบบคงที่ addTimerTask (ยาว threadId, timerTaskEvent งาน) {ThreadModel ThreadModel = getThreadModel (ThreadId); if (threadmodel! = null) {threadmodel.addtimer (task); return true; } return false; } / ** * เพิ่มงานเพิ่มงานลงในเธรดปัจจุบัน * * @param task * @return * / บูลีนสาธารณะแบบคงที่ addCurrentThreadTask (งาน TaskEvent) {เธรด currentThread = thread.currentThread; if (อินสแตนซ์ currentThread ของ threadmodel.mythread) {long threadId = currentthread.getId; threadmodel threadmodel = getThreadModel (threadId); if (threadmodel! = null) {threadmodel.addtask (task); }} return false; } / ** * เพิ่มงานตัวจับเวลาและเพิ่มงานลงในเธรดปัจจุบัน * * @param task * @return * / บูลีนสาธารณะแบบคงที่ addCurrentThreadTimerTask (งาน TimerTaskEvent) {เธรด currentThread = thread.currentThread; if (อินสแตนซ์ currentThread ของ threadmodel.mythread) {long threadId = currentthread.getId; threadmodel threadmodel = getThreadModel (threadId); if (threadmodel! = null) {threadmodel.addtimer (task); }} return false; -
ต่อไปมาดูการใช้งาน
รหัสแนะนำเธรดในบทความก่อนหน้า
โมฆะคงที่สาธารณะหลัก (String [] args) พ่น InterruptedException {// Thread Parallelism, หลายเธรดดำเนินการหลายงาน/ฟังก์ชั่นใหม่เธรดใหม่ (Run1 ใหม่). start; เธรดใหม่ (ใหม่ Run2). start; } // task1 คลาสคงที่ Run1 ใช้งาน runnable {@Override โมฆะสาธารณะเรียกใช้ {// ดำเนินการงาน 1 run1; // ดำเนินการงาน 3 run3; }} // task2 คลาสคงที่ run2 ใช้งาน runnable {@Override โมฆะสาธารณะเรียกใช้ {// ดำเนินการภารกิจ 3 run3; // ดำเนินการงาน 1 run1; // ดำเนินการงาน 2 run2; }} // ภารกิจ 1 โมฆะคงที่สาธารณะ run1 {system.out.println ("run1->" + system.currentTimeMillis); } // ภารกิจ 2 โมฆะสาธารณะคงที่ run2 {system.out.println ("run2->" + system.currentTimeMillis); } // ภารกิจ 3 โมฆะคงที่สาธารณะ run3 {system.out.println ("run3->" + system.currentTimeMillis); -ฉันเปลี่ยนรหัสเป็นโหมด
โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่น InterruptedException {// เธรดเป็นแบบขนานหลายเธรดดำเนินการหลายงาน/ฟังก์ชั่นยาว test1 = threadpool.addthreadmodel ("ทดสอบเธรด -1"); Long test2 = threadpool.addthreadmodel ("ทดสอบเธรด 2"); // เพิ่ม task threadpool.addtask (test1, ใหม่ run1); threadpool.addtask (test2, Run2 ใหม่); // เพิ่ม timer task threadpool.addtimertask (test1, timerrun1 ใหม่); threadpool.addtimertask (test2, timerrun2 ใหม่); } // task1 คลาสคงที่ run1 ขยาย taskEvent {@Override โมฆะสาธารณะเรียกใช้ {// ดำเนินการงาน 1 run1; // ดำเนินการงาน 3 run3; }} // task1 คลาสคงที่ timerrun1 ขยาย timertaskevent {public timerrun1 {super (500); // 500ms การดำเนินการไม่ จำกัด } @Override โมฆะสาธารณะเรียกใช้ {// ดำเนินการงาน 1 run1; // ดำเนินการงาน 3 run3; }} // task2 คลาสคงที่ run2 ขยาย taskEvent {@Override โมฆะสาธารณะเรียกใช้ {// ดำเนินการภารกิจ 3 run3; // ดำเนินการงาน 1 run1; // ดำเนินการงาน 2 run2; }} // task2 คลาสคงที่ timerrun2 ขยาย timertaskevent {public timerrun22 {super (500); // 500ms การดำเนินการไม่ จำกัด } @Override โมฆะสาธารณะเรียกใช้ {// ดำเนินการภารกิจ 3 run3; // เรียกใช้งาน 1 run1; // }} // task1 โมฆะสาธารณะคงที่ run1 {system.out.println ("run1->" + system.currentTimeMillis); } // task2 โมฆะสาธารณะคงที่ run2 {system.out.println ("run2->" + system.currentTimeMillis); } // ภารกิจ 3 โมฆะคงที่สาธารณะ run3 {system.out.println ("run3->" + system.currentTimeMillis); -ถัดไปลองดูที่เอฟเฟกต์การดำเนินการ
Run1-> 1472120543013RUN3-> 1472120543013RUN3-> 1472120543017RUN1-> 1472120543017RUN2-> 14721205 43017Run1-> 1472120543517RUN3-> 1472120543517RUN2-> 1472120543517RUN1-> 1472120544018RUN3-> 147 2120544018RUN2-> 1472120544018RUN1-> 1472120544520RUN3-> 1472120544520RUN2-> 1472120544520RUN1 -> 1472120545021RUN3-> 1472120545021RUN2-> 1472120545021RUN1-> 1472120545521RUN3-> 1472120545521
ทุกอย่างเป็นเรื่องปกติ
นี่คือโมเดลด้ายที่กำหนดเองของฉัน
ณ จุดนี้รูปแบบการทำเกลียวที่กำหนดเองของฉันเสร็จสมบูรณ์แล้ว
แล้วข้อดีและข้อเสียคืออะไร?
ข้อได้เปรียบคือการควบคุมการไหลของข้อมูลมีความชัดเจนมากรวมถึงสถานการณ์การดำเนินการในปัจจุบันรวมถึงเธรดที่ติดอยู่การตรวจสอบและการดำเนินการจับเวลางาน
ข้อเสียรูปแบบเธรดที่กำหนดเองนี้ยังไม่สามารถแก้ปัญหาความปลอดภัยของข้อมูลเธรดและพื้นที่วิกฤตได้และยังคงต้องแก้ไขโดยล็อคหรือรูปแบบอื่น ๆ ในเวลาที่เหมาะสม
ฉันหวังว่าพระเจ้าผู้ยิ่งใหญ่จะชี้ให้เห็นข้อบกพร่องดังนั้นฉันจึงสามารถแก้ไขได้ทันที