Те, кто читал мои предыдущие статьи, могут знать, что я занимаюсь разработкой игр. Многие из моих идей и отправных точек обрабатываются в соответствии с игровыми идеями, поэтому могут возникнуть конфликты с Интернетом и не соответствуют им.
Позвольте мне сказать вам, почему я хочу настроить модель потока?
Согласно игре MMORPG или MMORPG, которую я сделал, потоки делятся на основной поток, поток глобальной синхронизации, поток чата, поток команды, поток карты и распределение сообщений и поток сообщений и т. Д.
Некоторые столбцы должны контролироваться в соответствии с моим разделением и потоком данных.
Главное, что нужно сделать на игровом сервере, -это принять запрос команды игрока -> Соответствующая операция -> вернуть результат;
Все сообщения на стороне сервера будут зарегистрированы в диспетчере сообщений, а затем модель потока будет указана при регистрации сообщения.
Если сообщение необходимо отправить в поток карты игрока для обработки, при регистрации сообщения, вы должны использовать модель потока (распределение сообщений и диспетчерское поток MAP);
Давайте сначала проанализируем модель потока;
Прежде чем посмотреть на код модели потока, я сначала посмотрю на свою модель задачи
пакет net.sz.engine.thread; import java.io.serializable; import org.apache.log4j.logger; import net.sz.engine.structs.objectattribute; импорт net.sz.engine.structs.objectglobal;/** Model * * <br> * Автор Programmer <br> * Mail 492774. 13882122019 <br> */public абстрактный класс Taskevent реализует сериализуемые, клонируемый {частный статический окончательный logger log = logger.getlogger (taskevent.class); Частный статический последний длинный серийный режим = 4196020659994845804L; // ДАННЫЕ ВРЕМЕНИ ПРИВЕТСТВЕННЫЙ ПЕРЕКЛЮЧЕНИЕ Окончательный объект unattribute runother = new ObjectTtribute; // Время создания задач защищено долгое время; // задача уникальный идентификатор защищен Long TaskId; // Отмена задания защищенная логическая отмена = 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 objectTtribute getRunother {return runTher; } 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; // Чтобы изменить тело сгенерированных методов, выберите инструменты | Шаблоны. }}пакет net.sz.engine.thread;/** * Исполнитель Timer * * <br> * Автор неудачный программист <br> * mail [email protected] <br> * Телефон 13882122019 <br> */Общедоступный класс Timertaskevent Extends {private Static final Long SerialVersionuid = -83312962626262626262626262626266666666666262626262626266626666466666646466646666646466664646466666н. / *** Время начать выполнение*/ Защищенное длительное начало; / *** Будет ли выполнять один раз в начале*/ защищенный логический старт; / *** Время окончания*/ защищенное длительное время; / *** Количество выполнений*/ Защищенный int actionCount; / *** Время выполнения интервала*/ Защищенный интервал Int; / **** @param starttime Укажите время начала* @param iSstartAction, следует ли выполнять один раз в начале* @param EndTime Укажите время окончания* @param actioncount Укажите количество выполнений* @param интервал времени. this.starttime = starttime; this.startaction = iSstartAction; this.endtime = endtime; this.ActionCount = actionCount; this.Intervaltime = время интервала; } / *** Укажите время выполнения начала задачи** @param starttime Укажите время начала* @param iSstartAction, независимо от того, выполняется ли он один раз в начале* @param actionCount Укажите количество выполнений* @param. ActionCount, интервал); } / *** Указанное время окончания - это время окончания, а количество выполнений не обязательно*** @param iSstartAction выполнить, выполнять ли один раз в начале* @param endtime Укажите время окончания* @param actioncount Укажите количество выполнений* @param entertime Укажите время intermal intraptim Это (0, iSstartAction, EndTime, ActionCount, время интервала); } / *** Укажите время начала и время окончания** @param starttime Укажите время начала* @param endtime Укажите время окончания* @param. } / *** Указанное время выполнения и время интервала** @param actionCount Укажите количество выполнений* @param интервал времени Укажите время интервала* / public timertaskevent (int actioncount, int intermal) {this (0, false, 0, actionCount, QuardalTime); } / *** Неограничное выполнение после отправки* @param интервальное время. } public long getStarttime {return StartTime; } public void setStarttime (long StartTime) {this.StartTime = startTime; } public Boolean IsStartAction {return Startction; } 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 QuardalTime; } public void setIntervaltime (int интервал времени) {this.IntervalTime = expredTime; }}
Вот модель задачи и модель задач таймера;
пакет net.sz.engine.thread; import java.util.arraylist; import java.util.list; импорт java.util.concurrent.concurrentlinkedqueue; импорт net.sz.engine.structs.objectglobal; импорт net.sz.engine.utils.mailutil; org.apache.log4j.logger; import org.jboss.jandex.main;/** * Модель потока * <br> * Автор неудачный программист <br> * mail [email protected] <br> * Телефон 13882122019 <br> */Общественный класс. Logger.getLogger (ThreadModel.class); частный статический длинный ThreadId = 0; Защищенный статический конечный объект syn_object = new Object; защищенная длинная пьеса; Защищенное имя строки; Защищенный Long LastsendMail = 0; Защищенный окончательный ArrayList <Mythread> Threads = new ArrayList <>; /*** Список списка задач по потоке с безопасностью задач*/// Защищенный окончательный список <taskModel> taskQueue = new ArrayList <>; Защищенная окончательная comproundlinkedqueue <taskevent> taskqueue = new comprountlinkedqueue <>; / ***/ Защищенный окончательный список <timertaskevent> timerqueue = new Arraylist <>; // ложная идентификация Удалить резьбу Защищенная летучая логическая running = true; public ThreadModel (группа ThreadGroup) {this (группа, "без имени", 1); } public ThreadModel (string name) {this (threadpool.unknownthreadgroup, name, 1); } public ThreadModel (группа ThreadGroup, String name, int ThreatCount) {this (группа, имя, threadCount, null); } public ThreadModel (группа ThreadGroup, string name, int ThreadCount, Runnable Runnable) {synchronized (syn_object) {threadid ++; tid = thinkid; } for (int i = 1; i <= threadCount; i ++) {mythread thread; if (runnable == null) {thread = new mythread (tid, группа, это, имя + "-" + 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; } / ** * Получить пользовательский идентификатор потока * * @return * / public long getId {return this.tid; } / ** * Добавить новую задачу для каждой новой задачи, очередь задач должна быть пробуждена * * @param runnable * / public void addtask (taskevent runnable) {taskqueue.add (runnable); синхронизированный (taskQueue) {/ * Разбудить очередь и начать выполнять */ taskQueue.notifyall; }}/** * Добавить задачу таймера в поток * * @param Runnable */public void Addtimer (Timertaskevent Runnable) {synchronized (timerqueue) {if (runing) {// выполнять один раз в начале if (runnable.startaction) {addTask (runnable); } timerqueue.add (runnable);} else {log.error ("Поток остановился"); }}}} // <editor-fold defaultState = "COLLAPSED" DESC = "TIMER THIDER Public void"> / *** TIMER THIDE Executor* / public void Timerrun {ArrayList <Timertaskevent> taskModels; Synchronized (Timerqueue) {// Если очередь не пуста, выберите таймер очередь taskModels = new ArrayList <> (TimerQueue); } if (! taskmodels.isempty) {for (timertaskevent timerevent: taskmodels) {int execcount = timerevent.getrunother.gettinvalue ("execcount"); long в прошлое = timerevent.getrunother.getlongvalue ("astaxectime"); long nowtime = System.currentTimeMillis; if (в последний раз == 0) {timerevent.getRunother.put ("tastexectime", сейчас время);} else if (timerevent.iscancel) {// Если задача была отменена синхронизирована (timerqueue) {timerqueue.remove (timerevent); } log.debug ("Очистить задачу таймера:" + timerevent.getclass.getname);} else if (nowtime> timerevent.getStarttime // Будь то время начала. timerevent.getendtime) // Определить время окончания && (nowtime - fasttime> = timerevent.getIntervaltime)) // Определить, удовлетворено ли время интервала с момента последнего выполнения {// Timer выполнения подчинения первым, кто выполняет это. execcount); timerevent.getrunother.put ("astaxectime", nowtime); nowtime = system.currenttimemillis; // определить условие удаления if ((timerevent.getendtime> 0 && nowtime <timerevent.getendtime) || Timerqueue.remove (Timerevent); } log.debug ("Timer Cleaning Timer:" + timerevent.getClass.getName); }}}}}}} // </editor-fold> // <editor-fold defaultState = "COLLAPSED" DESC = "View Stack Stack Public void ShowStackTrace">/**** View Thread Stack*/public void showStackTrace {StringBuilder buf = new StringBuilder; Для (mythread currentThread: Threads) {long procc = System.currentTimeMillis - currentThread.getLastExeCuteTime; if (procc> 5 * 1000 && procc <86400000l) {// менее 10 дней // Потому что время многопоточного времени может быть нежным. Stuck-> ") .append (procc/1000f) .append (" s/n ") .append (" выполнить задачу: ") .append (currentthread.getlastcommand.getClass.getName); try {stackTraceElement elements = currentThread.getStacktrace; для (int i = 0; I <elements.lendense; i ++ {i ++ {i ++ {i ++ {i ++ {i ++ {i ++ {i ++ {i+stack. .append (элементы [i] .getClassname) .append (".") .append (элементы [i] .getmethodname) .append ("("). Append (elements [i] .getfilename) .append (";"). Приложение (элементы [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-FANDSENDMAIL> 5 * 60 * 1000) {LastSendMail = System.CurrentTimeMillis; Mailutil.Sendmail («Выполнение нит Objectglobal.platform + "идентификатор сервера-" + objectglobal.serverid, toString); }}} // </editor-fold> @override public void run {mythread currentThread = (mythread) thread.currentThread; while (Runing) {while (taskqueue.isempty && running) {try {/* очередь задачи пуста, тогда новая задача ждет, когда новая задача будет соединяться и разбудить*//синхронизированный (taskqueue) {taskqueue.wait (500); }} catch (прерывание Exception IE) {log.Error (IE); }}/* Получить задачу для выполнения*/if (Runing) {currentThread.lastCommand = null; currentThread.lastCommand = taskQueue.poll; } if (currentThread.lastCommand! = null) {if (currentThread.lastCommand.iscancel) {// Если задача была отменена продолжение; }/* Выполнить задачу* /// r.setsubmittimel; currentthread.lastexeCuteTime = System.CurrentTimeMillis; try {currentThread.lastCommand.Run;} Catch (Exception E) {log.Error ("kavemer <" + currentThread.getName + "> executuute the Task <" + currentThread.getScle.getScl.getScl.getScl.getSclasm.getSclasm.getScl.getSclasm.getSclasm. Была обнаружена ошибка: ", e); } long Timel1 = System.currentTimeMillis - CurrentThread.lastExeCutetime; if (timel1 <= 20) {} else if (timel1 <= 100l) {log.info ("konay <" + currentThread.getName + ""> Заполнил задачу: " + currentThread.lastCommand.toString +" Time: " + timel1);} else (timel1 <= 200l) {log. + ""> Долгосрочное выполнение завершения задачи:" + currentThread.lastCommand.toString + "" рассмотреть ". быть удаленным "Скрипт задачи трудоемкий:" + timel1); } currentThread.lastExeCuteTime = 0; }} log.error ("ends inders, worker <" + thread.currentthread.getName + ""> exit "); } / *** Пользовательский поток* / public Class Mythread Extends Thread { / **** @param TID TID ID потока* @param Group Group* @param запустить метод выполнения* @param Имя потока* / public mithread (long tid, группа Threadgroup, Runnable Run, String name) {super (run, name); } // Пользовательский идентификатор потока Public long _id; // Задача исполнения Public volatile Taskevent LastCommand; // Время начать выполнение задачи Public Colatile Long LongexeCutetime = 0; public taskevent getlastcommand {return lastcommand; } public long getLastExeCutetime {return astexeCutetime; } / ** * return Think Custom ID * * @return * / @Override public long getId {return _id; }} / *** Остановите поток, установите состояние остановки потока и не будет немедленно прекращать поток* / public void Stop {this.Runing = false; } public boolean isruning {return running; } @Override public String toString {return "Thread {" + "tid =" + tid + ", name =" + this.getName + '}'; }}
Я построил из Threadmodel
public ThreadModel (группа ThreadGroup, название строки, int ThreatCount, Runnable Runnable) {synchronized (syn_object) {threadid ++; tid = thinkid; } for (int i = 1; i <= threadCount; i ++) {mythread thread; if (runnable == null) {thread = new mythread (tid, группа, это, имя + "-" + tid + "-" + i);} else {thread = new Mythread (tid, group, runnable, name + "-" + tid + " +" + i); } Thread.Start; Threads.add (Thread); } this.name = name; }Как можно увидеть, здесь я запускаю класс Thread Thread, объявленный
Почему я думаю об этом? Например, если я обрабатываю данные записи журнала, например, без общих данных и отсутствие потока обработки критической области, я могу рассмотреть возможность использования N потоков для обработки такой работы; это не будет производить грязные данные;
Если я хочу объединиться и запросить навыки, мне нужно обработать одну очередь, то в ThreadModel должен быть только один Mythread. Это не считается последовательным выполнением режима блокировки (или выполнением очередей) для решения проблемы обмена данными и критической областью потока, которая больше не зависит от замков;
Я очень уродливый, пожалуйста, прости меня
Как показано на рисунке выше, в каждой ThreadModel будет две очереди, один срокветец и другой задача, и там будет глобальный поток таймера;
Функция глобального потока таймера состоит в том, чтобы обработать и обнаружить, что сроки в ThreadModel должны быть выполнены, поэтому он добавляется в команду TaskVENT; Окончательное выполнение - это очередь задачи
Почему Timetaskevent должен храниться в соответствующей ThreadModel? Это связано с тем, что, например, после моего потока A (экземпляр Threadmodel) работает в течение определенного периода времени, мне нужно закрыть и освободить ресурсы, поэтому мне нужно пойти в другие места, чтобы найти соответствующий срок и удалить его;
package net.sz.engine.thread;import java.util.HashMap;import java.util.Map;/** * * <br> * author Falling programmer<br> * mail [email protected]<br> * phone 13882122019<br> */class TimerThread extends Thread { private static final Object SYN_OBJECT = new Object; public Timerthread {super (threadpool.globlthreadgroup, "Глобальный поток таймера"); } @Override public void run {while (true) {synchronized (syn_object) {try {syn_object.wait (2);} catch (прерывание ex) {}} hashmap <long, thintmodel> hashmap = new Hashmap <> (thinkpool.getThread); HashMap.EntrySet) {long key = intirpTect.getKey; threadModel value = intirpTest.getValue; value.timerrun; }}}}
Диспетчер модели потоков
пакет 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.globtimeryvent; импорт. org.apache.log4j.logger;/** * Manager * * <br> * Автор неудачный программист <br> * mail [email protected] <br> * Телефон 13882122019 <br> */public class threatpool {static private final log = logger.getlogger (thinkpool.class); Статическая публичная финальная длинная Globlthread; Статический частное финальное время Timerthreadgltimerthread; Статический финальный длинный длинный контроль Статическая публичная окончательная темпа Globlthreadgroup = new Threadgroup ("Global Threadgroup"); Static Public Final ThreadGroup UnlingThreadGroup = New Threadgroup (Globlthreadgroup, «Неизвестная Threadgroup»); Статический частный финальный финал concurrenthashmap <long, threadmodel> threadmap = new concurrenthashmap <>; public static void main (string [] args) {threadpool.addtimertask (globlthread, new timertaskevent (1000) {@overridepublic void run {log.error ("sssss");}}); } static {// Создать глобальную нить globlthread = addthreadmodel (globlthreadgroup, "globlthread"); // Выполните указанное время задачи, чтобы запустить шаги addTimeRtask (globlthread, new GlobtimeRevent (scriptManager.getInstance.getBasScriptEntry)); // Запросить модель времени потребления сервера addTimeRatask (Globlthread, New PrintlnservermemoryTimeRevent); // Создать потоку таймера globltimerthread = new Timerthread; Globltimerthread.start; // Проверьте тему stuck checkThreadTimerThreadModel = addThreadModel (globlthreadgroup, "Check Threadtimer Event"); AddTimeRtask (CheckThreadThierThreadModel, New CheckThreadTimeRevent); } / ** * При удалении указанной модели идентификационного потока установите состояние в состояние остановки * * @param tid * @return * / static public threadmodel remove (long tid) {threadmodel remove = threadmap.remove (tid); if (удалить! = null) {remove.stop; } вернуть удалить; } / ** * Получить все потоки в пуле потоков * * @return * / static public concurrenthashmap <long, threadmodel> getThreadMap {return ThreadMap; } / ** * Получить поток в пуле потоков * * @param thinkid * @return * / static publicmodel getThreadModel (long ThinkId) {threadModel get = threadmap.get (thinkId); if (get == null) {log.error («Модель потока не может быть найдена:« + thinkid, новое исключение («Модель потока не может быть найдена:» + thinkid)); } return get; } / ** * Зарегистрируйте поток в пул потоков * <br> * По умолчанию группировка UnknownThreadGroup * * @param name name * @return * / static public long addthreadmodel (string name) {return addThreadModel (UnnownlowThreadGroup, name); } / ** * Зарегистрируйте поток в пул потоков * <br> * Группирование по умолчанию UnknownthreadGroup * * @param имени ThreadName * @param ThreatCount ThreatCount * @return * / static public long addThreadModel (string name, int tradeCount) {return AddThreadModel (UnknownkThroup, name, ThinkCount); } / *** Зарегистрируйте поток с помощью пула потоков** @param Группа Информация о группировке* @param Имя поток* @return* / static public long addthreadmodel (группа Threadgroup, String name) {return addThreadModel (группа, имя, 1); } / *** Зарегистрируйте поток с помощью пула потоков** @param Группа Группа Информация* @param namename* @param threadcount treadcount* @return* / static public long addThreadModel (группа ThreadGroup, nateCount, int tradeCount) {return addThreadModel (группа, имя, null, tradeCount); } /** * Register a thread with the thread pool* * @param group Threadgroup information* @param name Threadname* @param runnable * @param threadcount Threadcount* @return */ static public long addThreadModel(ThreadGroup group, String name, Runnable runnable, int threadcount) { ThreadModel threadModel = new ThreadModel(group, name, threadcount, runnable); вернуть AddThreadModel (ThreadModel); } / ** * Зарегистрируйте поток с помощью пула потоков * * @param threadmodel * / static public long AddThreadModel (ThreadModel ThreadModel) {threadMap.put (threadmodel.getId, ThreadModel); return ThreadModel.getId; } / ** * Добавить задачу * * @param thinkid * @param task * @return * / static public boolean addtask (long threadid, taskevent task) {threadmodel threadmodel = getThreadModel (thinkId); if (threadmodel! = null) {threadmodel.addtask (задача); вернуть true; } вернуть false; } / ** * Добавить Timer Task * * @param Thinkid * @param task * @return * / static public boolean addtimertask (long threadid, timertaskevent task) {threadmodel threatmodel = getThreadModel (ThinkId); if (threadmodel! = null) {threadmodel.addtimer (задача); вернуть true; } вернуть false; } / ** * Добавить задачу, добавьте задачу в текущий поток * * @param task * @return * / static public boolean addcurrentthreadtask (taskevent task) {thread currentthread = thread.currentthread; if (currentThread экземпляр ThreadModel.mythread) {long ThinkId = currentThread.getId; ThreadModel ThreadModel = getThreadModel (ThreadId); if (ThreadModel! = null) {ThreadModel.AddTask (task); return true; }} вернуть false; } / ** * Добавить задачу таймера и добавить задачу в текущий поток * * @param task * @return * / static public boolean addcurrentthreadtimertask (timertaskevent task) {thuceThread = Thread.CurrentThread; if (currentThread экземпляр ThreadModel.mythread) {long ThinkId = currentThread.getId; ThreadModel ThreadModel = getThreadModel (ThreadId); if (ThreadModel! = null) {ThreadModel.AddTimer (задача); return true; }} вернуть false; }}
Далее, давайте посмотрим на использование
Код введения потока в предыдущей статье
public static void main (string [] args) бросает прерывание. новая ветка (новый run2) .start; } // task1 static class RUN1 реализует runnable {@Override public void Run run {// repute task 1 run1; // repute task 3 run3; }} // task2 static class RUN2 реализует runNable {@Override public void run {// repute task 3 Run3; // repute task 1 run1; // выполнить задачу 2 Run2; }} // задача 1 public static void run1 {system.out.println ("run1->" + system.currenttimemilsis); } // задача 2 public static void run2 {System.out.println ("run2->" + system.currentTimeMillis); } // задача 3 public static void run3 {System.out.println ("run3->" + system.currenttimemillis); }Я переключил код в режим
public static void main (string [] args) бросает прерывание {// потоки параллельны, несколько потоков выполняют множественные задачи/функция long test1 = threadpool.addthreadmodel ("test thread-1"); Long Test2 = ThreadPool.AddThreadModel ("Тестовая потока 2"); // Добавить задачу threadpool.addtask (test1, new Run1); Threadpool.addtask (test2, new Run2); // Добавить таймер задача threadpool.addtimertask (test1, new Timerrun1); ThreatPool.AddTimeRtask (test2, new Timerrun2); } // task1 static class run1 extends taskevent {@override public void run {// выполнить задачу 1 run1; // выполнить задачу 3 Run3; }} // task1 static class timerrun1 extends timertaskevent {public timerrun1 {super (500); // 500 мс неограниченное выполнение} @override public void run {// выполнить задачу 1 run1; // выполнить задачу 3 Run3; }} // task2 static class run2 extends taskevent {@override public void run {// repute task 3 run3; // выполнить задачу 1 run1; // выполнить задачу 2 run2; }} // task2 static class timerrun2 extends timertaskevent {public timerrun2 {super (500); // 500 мс неограниченное выполнение} @override public void run {// execute task 3 Run3; // выполнить задачу 1 Run1; // execute task 2 Run2; }} // task1 public static void run1 {system.out.println ("run1->" + system.currenttimemillis); } // task2 public static void run2 {System.out.println ("run2->" + System.currentTimeMillis); } // задача 3 public static void run3 {System.out.println ("run3->" + system.currenttimemillis); }Далее, давайте посмотрим на эффект выполнения
RUN1-> 1472120543013RUN3-> 1472120543013RUN3-> 1472120543017RUN1-> 1472120543017RUN2-> 14721205 43017RUN1-> 1472120543517RUN3-> 1472120543517RUN2-> 1472120543517RUN1-> 1472120544018RUN3-> 147 2120544018RUN2-> 1472120544018RUN1-> 1472120544520RUN3-> 1472120544520RUN2-> 14721205444520RUN1 -> 1472120545021RUN3-> 1472120545021RUN2-> 1472120545021RUN1-> 1472120545521RUN3-> 1472120545521
Все нормально;
Это моя пользовательская модель потоков;
На этом этапе моя пользовательская модель потока была завершена;
Так каковы преимущества и недостатки?
Преимущество состоит в том, что управление потоком данных очень ясно, включая текущую ситуацию выполнения, а также потоки застряли мониторинг и выполнение таймера задач;
Недостатки, эта пользовательская модель потока по -прежнему не может решить проблему безопасности данных потока и критической области, и ее все еще нужно решить с помощью замков или других форм в соответствующее время;
Я надеюсь, что великие боги укажут на недостатки, поэтому я смогу исправить их немедленно.