Ceux qui ont lu mes articles précédents savent peut-être que je fais du développement de jeux. Beaucoup de mes idées et de mes points de départ sont gérés en fonction des idées de jeu, donc il peut y avoir des conflits avec le Web et ne sont pas conformes à cela.
Permettez-moi de vous dire pourquoi je souhaite personnaliser le modèle de fil?
Selon le jeu MMORPG ou MMORPG que j'ai réalisé, les threads sont divisés en thread principal, thread de synchronisation global, thread de chat, thread d'équipe, thread de carte et dispositif de distribution de messages et threads de livraison, etc.
Certaines colonnes doivent être contrôlées en fonction de ma division et de mon flux de données.
La principale chose à faire dans le serveur de jeux est d'accepter la demande de commande du lecteur -> Opération correspondante -> Retour le résultat;
Tous les messages côté serveur seront enregistrés dans le gestionnaire de messages, puis le modèle de thread sera spécifié lorsque le message sera enregistré.
Si le message doit être soumis au thread de carte du lecteur pour le traitement, lors de l'enregistrement du message, vous devez utiliser le modèle de thread (Distribution de message de carte et thread de répartition);
Analysons d'abord le modèle de thread;
Avant de regarder le code du modèle de thread, je regarde d'abord mon modèle de tâche
package net.sz.engine.thread; import java.io.serializable; import org.apache.log4j.logger; import net.sz.engine.struct.objectAttribute; import net.sz.engine.struct.objectglobal; / ** * Modèle de tâche * * <br> * AuthrArmmer <brmmer 13882122019 <br> * / Classe abstraite publique Taskevent implémente sérialisable, clonable {private static final logger log = logger.getLogger (taskevent.class); Final statique privé long SerialVersionUID = 4196020659994845804L; // Runtime Data Private Transient Final ObjectAttribute Runother = new ObjectAttribute; // temps de création de tâche protégée longue création; // tâche ID unique protégé Long TaskId; // Tâche annulée protégée Boolean annule = false; public taskevent {this.runother.put ("Soumidertime", System.currentTimeMillis); CreateTime = System.Currenttimemillis; annuler = false; taskId = objectGlobal.getuuid; } public long getcreatetime {return CreateTime; } public void setCreateTime (long createTime) {this.createtime = CreateTime; } public long getSUBMitTime {return this.runother.getLongValue ("Soumistime"); } public ObjectAttribute Getrunother {return Runother; } public boolean iscancel {return annule; } public void setCancel (booléen annule) {this.cancel = annuler; } Public Abstract Void Run; @Override Public Object Clone lève ClonenotsupportException {return super.clone; // Pour modifier le corps des méthodes générées, choisissez des outils | Modèles. }}Package net.sz.engine.thread; / ** * Timer Executor * * <br> * PROGRAMMER AUTHER UN AUTEUR <br> * Mail [email protected] <br> * Téléphone 13882122019 <br> * / Public Résumé Classe Timertaskevent Étend Taskevent {private Static Final Serialversiid = -8331296295264699207l; / ** * Il est temps de démarrer l'exécution * / Protected Long Starttime; / ** * Il faut exécuter une fois au début * / Boolean StartAction protégé; / ** * Heure de fin * / Longue durée protégée; / ** * Nombre d'exécutions * / Protected int actionCount; / ** * Temps d'exécution d'intervalle * / Int intervaltime protégé; / ** * * @param starttime Spécifiez l'heure de début * @param isStartAction si il faut exécuter une fois au début * @param Fintime Spécifiez l'heure de fin * @param actionCount Spécifiez le nombre d'exécutions * @Param Intervaltime Spécifiez l'intervalle d'heure * / Public TimertSkevent (Long Starttime, Boolean IsstartAction, LongneTime, int ActionCount, int intervaltime) {super; this.starttime = startTime; this.startAction = isStartAction; this.endtime = endtime; this.ActionCount = actionCount; this.intervaltime = intervaltime; } / ** * Spécifiez le temps d'exécution de démarrage de la tâche * * @param starttime Spécifiez l'heure de début * @param isStartAction s'il est exécuté une fois au début * @param actionCount Spécifiez le nombre d'exécutions * @param intervaltime Spécifiez l'heure d'intervalle * / public TimertSkevent (Long Starttime, Boolean IsstartAction, int ActionCount, int intervaltime) {this (startime, isstAraction, int ActionCount, int intervaltime) {this (startime, isstAraction, int ActionCount, Int ActionCount, Intervaltime); } / ** * L'heure de fin spécifiée est la fin de l'heure, et le nombre d'exécutions n'est pas nécessairement suffisant * * @param isStartAction s'il faut exécuter une fois au début * @param fini temps spécifier le temps d'intervalle * @param actionCount Spécifiez le nombre d'exécutions * @param intervalle temps Spécifiez le temps d'intervalle * * / public TimertSkevent (Boolean isStartActure, longue fin, INTTROCTOR ce (0, isStartAction, Endtime, ActionCount, Intervaltime); } / ** * Spécifiez l'heure de début et l'heure de fin * * @param starttime Spécifiez l'heure de début * @param Fintime Spécifiez l'heure de fin * @param intervaltime Spécifiez l'heure d'intervalle * / public Timemertaskevent (Long Startime, Long Fintime, int intervaltime) {this (starttime, false, fin, -1, intervalle); } / ** * Les temps d'exécution et le temps d'intervalle spécifié * * @param actionCount Spécifiez le nombre d'exécutions * @param intervaltime Spécifiez l'heure d'intervalle * / public timertaskevent (int actionCount, int intervaltime) {this (0, false, 0, actionCount, Intervaltime); } / ** * Exécution illimitée après la soumission * @param intervaltime intervalpe Time * / public TimertSkevent (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 = finm; } 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; }}
Voici le modèle de tâche et le modèle de tâche de minuterie;
Package net.sz.engine.thread; import java.util.arraylist; import java.util.list; import java.util.concurrent.concurrentLinkedqueue; import net.sz.engine.struct.ObjectGlobal; import net.sz.engine.utils. org.apache.log4j.logger; import org.jboss.jandex.main; / ** * Modèle de thread * <br> * Programmer défaillance de l'auteur <br> * Mail [email protected] <br> * Téléphone 13882122019 <br> * / Classe publique ThreadModel implémente Runnable {private static final logger logger log Logger.getLogger (ThreadModel.class); Long ThreadId privé = 0; objet final statique protégé syn_object = nouvel objet; protégé de Long Tid; nom de chaîne protégé; protégé long LastSendMail = 0; Final ArrayList final protégé <Mythread> Threads = new ArrayList <>; / ** * Liste des tâches Liste des tâches de filetage * / // Liste finale protégé <TaskModel> taskQueue = new ArrayList <>; Protégé final concurrentLinkedQueue <taskevent> taskqueue = new concurrentLinkedQueue <>; / ** * / Liste finale protégée <Tirmertaskevent> TIMERQUEUE = new ArrayList <>; // FAUX Identité Supprimer le filetage protégé volatile booléen running = true; public threadModel (groupe ThreadGroup) {this (groupe, "aucun nom", 1); } public threadModel (nom de chaîne) {this (threadpool.unknownthreadgroup, name, 1); } public threadModel (groupe threadGroup, nom de chaîne, int threadCount) {this (groupe, nom, threadCount, null); } public threadModel (groupe threadGroup, nom de chaîne, int threadcount, runnable runnable) {synchronisé (syn_object) {threadId ++; tid = threadId; } pour (int i = 1; i <= threadCount; i ++) {mythread thread; if (runnable == null) {thread = new myThread (tid, groupe, this, name + "-" + tid + "-" + i);} else {thread = new Mythread (tid, groupe, runnable, name + "-" + id + "-" + i); } thread.start; threads.add (thread); } this.name = name; } / ** * Nom du thread * * @return * / public String getName {return name; } / ** * Obtenez l'ID personnalisé du thread * * @return * / public long getID {return this.tid; } / ** * Ajouter une nouvelle tâche pour chaque nouvelle tâche, la file d'attente de tâche doit être éveillée * * @param runnable * / public void addTask (taskevent runnable) {taskqueue.add (runnable); synchronisé (taskqueue) {/ * réveillez la file d'attente et commencez à exécuter * / taskqueue.notifyall; }} / ** * Ajoutez une tâche de minuterie au thread * * @param runnable * / public void addtimer (TimertAsKevent Runnable) {synchronisé (TimerQueue) {if (Runing) {// Exécuter une fois au début if (runnable.startAction) {addTask (runnable); } timerqueue.add (runnable);} else {log.error ("thread a arrêté"); }}}} // <editor-fold defaultState = "Collapsed" desc = "Time Thread Executor public void timerrun"> / ** * Thread Thread Executor * / public void timerrun {ArrayList <MimertaSkevent> taskModels; synchronisé (TIMERQUEUe) {// Si la file d'attente n'est pas vide, retirez la file d'attente TaskModels = new ArrayList <> (TIMERQUEUE); } if (! TaskModels.iSempty) {for (TimertaSkevent timeRevent: taskModels) {int execcount = timeRevent.getRunother.getInValue ("EXECCOUNT"); long dernier = timerevent.getRunother.getLongValue ("LastExectime"); Long NowTime = System.CurrentTimeMillis; if (Lasttime == 0) {timerevent.getRunother.put ("LastExectime", maintenantTime);} else if (TimeRevent.iscancel) {// If the task a été annulé synchronisé (TIMERQUIEUe) {timerQueue.Remove (timeRevent); } Log.Debug ("Clean the Timer Task:" + TimeRevent.getClass.getName);} else if (Nowtime> tinrevent.getStarttime // si l'heure de démarrage est satisfaite && (maintenant - TimeRevent.getSubmittime> timerevent.getIntervaltime) // timerevent.getEndTime) // déterminer l'heure de fin && (maintenant - dernier - = TimeRevent.getIntervaltime)) // Déterminez si l'intervalle a été satisfait depuis la dernière exécution {// le temporisateur d'exécution de soumission est le premier à exécuter this.addtask (TimeRevent); // enregistrer un exécution ++; TimeRevent.GetRunother. EXECCOUNT); timerevent.getRunother.put ("LastExectime", NowTime); NowTime = System.Currenttimemillis; // Déterminez la condition de suppression if ((TimeRevent.gettendTime> 0 && maintenant <TimeRevent.getTenTime) || (TimeRevent.getActionCount> 0 && TiMerevent) {Execute TIMERQUEUE.REMOVE (TimeRevent); } log.debug ("tâche de nettoyage de la minuterie:" + timerevent.getClass.getName); }}}}}}} // </ editor-fold> // <editor-fold defaultState = "Collapsed" desc = "afficher la pile de thread public void showstacktrace"> / ** * * View Thread Stack * / public void showStackTrace {StringBuilder buf = new StringBuilder; pour (MyThread CurrentThread: Threads) {long procc = System.Currenttimemillis - CurrentThread.getLastexEcuTime; if (procc> 5 * 1000 && procc <86400000l) {// moins de 10 jours // parce que le temps de fonctionnement multhread peut être inexacturé. Stuck-> ") .append (procc / 1000f) .append (" s / n ") .append (" Exécuter la tâche: ") .append (currentThread.getLastCommand.getClass.getName); try {stackTraceElement elements = currentThread.getStackTrace; for (int i = 0; i <elements.Legth; i ++) {buf.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 ("Thread Exécution est colo ObjectGlobal.platform + "Server id-" + objectGlobal.serverId, toString); }}} // </ editor-fold> @OverRide public void run {mythread currentThread = (mythread) thread.currentThread; while (runing) {while (taskqueue.isempty && running) {try {/ * La file d'attente de tâche est vide, alors une nouvelle tâche attend une nouvelle tâche pour rejoindre et être réveillé * / synchronisé (taskQueue) {taskQueue.Wait (500); }} catch (InterruptedException ie) {log.Error (ie); }} / * Sortez la tâche pour exécuter * / if (runing) {currentThread.lastCommand = null; currentThread.lastCommand = taskQueue.poll; } if (currentThread.lastCommand! = null) {if (currentThread.lastCommand.iscancel) {// Si la tâche a été annulée, continuez; } / * Exécuter la tâche * /// R.SetSuBmittimel; currentThread.LastexEcuTime = System.Currenttimemillis; Try {CurrentThread.LastCommand.Run;} Catch (Exception e) {Log.Error ("Worker <" "+ CurrentThread.getName +" "> Exécuter la tâche <" + Antrolred.llastCommand.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass.Glass. a été rencontré: ", e); } long timel1 = System.currenttimemillis - CurrentThread.LastexEcuTeTime; if (timel1 <= 20) {} else if (timel1 <= 100l) {log.info ("worker <" "+ currentThread.getName +" "> terminé la tâche:" + currentThread.lastCommand.tostring + "Time d'exécution:" + timel1);} else if (Timel1 <= 200L) {log.info ("Worker ""> Exécution à long terme de l'achèvement de la tâche: "+ CurrentThread.lastCommand.Tostring +" "Considérez" la logique de script de la tâche qui prend du temps: "+ Timel1);} else {Log.info (" Worker <"" + CurrentThread.getName + ""> Exécuter l'achèvement de la tâche pour le temps: "+ CurrentThread.lastCommand.tosTring +" supprimé "Le script de tâche prend du temps:" + timel1); } currentThread.LastexEcuTeTime = 0; }} log.Error ("Thread se termine, travailleur <" "+ thread.currentThread.getName +" "> exit"); } / ** * Thread personnalisé * / classe publique MyThread étend Thread {/ ** * * @param Tid Custom Thread ID * @param groupe de groupe * @param Run Execution Method * @param Nom du thread Nom * / public Mythread (Long Tid, ThreadGroup Group, Runnable Run, String Name) {super (groupe, run, nom); this._id = tid; } // ID personnalisé du thread public long _id; // Tâche d'exécution Public Volatile Taskevent LastCommand; // Il est temps de commencer à exécuter la tâche publique Volatile Long LastExecuTime = 0; public taskevent getlastCommand {return lastCommand; } public long getlastexEcuTeTime {return lastExecuTime; } / ** * retour du thread ID personnalisé * * @ return * / @Override public long getID {return _id; }} / ** * Arrêtez le thread, définissez l'état d'arrêt du thread et ne terminera pas le thread immédiatement * / public void stop {this.runing = false; } public boolean isruning {return running; } @Override public String toString {return "Thread {" + "tid =" + tid + ", name =" + this.getName + '}'; }}
J'ai construit à partir de threadmodel
public threadModel (groupe threadGroup, nom de chaîne, int threadCount, runnable runnable) {synchronisé (syn_object) {threadId ++; tid = threadId; } pour (int i = 1; i <= threadCount; i ++) {mythread thread; if (runnable == null) {thread = new myThread (tid, groupe, this, name + "-" + tid + "-" + i);} else {thread = new Mythread (tid, groupe, runnable, name + "-" + id + "-" + i); } thread.start; threads.add (thread); } this.name = name; }Comme on peut le voir, ici, je gère la classe de fil Mythread déclaré
Pourquoi est-ce que je pense à cela? Par exemple, si je traite des données de rédaction de journaux, telles que aucune donnée partagée, et pas de flux de traitement de la zone critique du thread, je peux envisager d'utiliser N threads pour traiter ces travaux; Il ne produira pas de données sales;
Si je veux faire équipe et demander des compétences en casting, je dois traiter une seule file d'attente, alors il ne doit y avoir qu'un seul mythread dans ThreadModel. Cela ne compte pas comme un mode de blocage l'exécution en série (ou l'exécution de la file d'attente) pour résoudre le problème du partage des données et de la zone critique du thread, qui ne dépend plus des verrous;
Je suis très moche, pardonne-moi s'il te plait
Comme indiqué dans l'image ci-dessus, il y aura deux files d'attente dans chaque threadModel, une Timetaskevent et l'autre Taskvent, et il y aura un thread de minuterie global;
La fonction du thread de temporisation global est de traiter et de constater que le timetaskevent dans le threadModel doit être exécuté, il est donc ajouté à l'équipe Taskvent; L'exécution finale est la file d'attente Taskvent
Pourquoi Timetaskevent devrait-il être stocké dans le threadModel correspondant? C'est parce que, par exemple, après que mon fil A (instance ThreadModel) fonctionne pendant un certain temps, j'ai besoin de fermer et de libérer des ressources, donc je dois aller vers d'autres endroits pour trouver la TimeTask correspondante et le supprimer;
Package net.sz.engine.thread; import java.util.hashmap; import java.util.map; / ** * * <br> * Auteur Falling Programmer <br> * Mail [email protected] <br> * Téléphone 13882122019 <br> * / Class tiserthread Extend Thread {private STATIC OBJECT STATIC FINAL SYN_OBJECT = NOUVEAU Objet; 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.getTheredMap); for (map.Entring < hashmap.entrySet) {long key = entryset.getKey; ThreadModel Value = entrySet.getValue; value.timerrun; }}}}
Manager modèle de thread
Package net.sz.engine.thread; import java.util.hashmap; import java.util.concurrent.concurrenthashmap; import net.sz.enger.script.manager.scriptManager; import net.sz.engine.timer.globtimerevent; importation; org.apache.log4j.logger; / ** * Manager de thread * * <br> * PROGRAMMER AUTHER UN AUTHER <br> * Mail [email protected] <br> * Téléphone 13882122019 <br> * / public class Threadpool {static private final logger Log = Logger.getLogger (Threadpool.Class); static privé Logger Logger = Logger.getLogger (ThreadPool.Class); Final public statique Long Globlthread; TimerThreadgloBltimerThread à timerReredGloblMimer de statique statique; Final statique Long CheckThreadtimerThreadModel; STATIC PUBLIC FINAL THELGROUP GloBlThreadGroup = nouveau ThreadGroup ("Global ThreadGroup"); STATIC PUBLIC FINAL THELGROUP CONNUTSHTHERDGROUP = nouveau ThreadGroup (GloBlThreadGroup, "Unknown ThreadGroup"); Final privé statique final concurrenthashmap <long, threadModel> threadmap = new concurrenthashmap <>; public static void main (String [] args) {threadpool.addtimertask (GloBlthread, new Timemertaskevent (1000) {@OverRidePublic void run {log.error ("sssss");}}); } static {// Créer le thread global GloBlThread = addThreadModel (GloBlThreadGroup, "GloBlthread"); // Exécuter le synchronisation de la tâche spécifiée pour déclencher les pas AddTimertask (GloBlThread, new GlobTimeRevent (scriptManager.getInstance.getBasescriptRy)); // Interroge le modèle de synchronisation de la consommation de serveur addTimertask (Globlthread, new printlnServerMemoryTimeRevent); // Créer le thread de minuterie globltimerThread = new TimerThread; GloBlTimerThread.start; // Vérifiez le thread Stuck CheckThreadTimerThreadModel = addThreadModel (GloBlThreadGroup, "Vérifier l'événement Threadtimer"); AddTimertAsk (CheckThreadTimerThreadModel, new CheckThreadTimeTevent); } / ** * Lors de la suppression du modèle de thread ID spécifié, définissez l'état sur l'état d'arrêt * * @param tid * @return * / static public ThreadModel retire (long tid) {ThreadModel reous = ThreadMap.Remove (TID); if (retire! = null) {repos.stop; } return supprimer; } / ** * Obtenez tous les threads dans le pool de threads * * @return * / statique public concurrenthashmap <long, threadModel> getthreadmap {return threadmap; } / ** * Obtenez un thread dans le pool de threads * * @param threadid * @return * / static public threadModel getThreadModel (long threadId) {ThreadModel get = ThreadMap.get (threadId); if (get == null) {log.Error ("Le modèle de thread ne peut pas être trouvé:" + ThreadId, nouvelle exception ("Le modèle de thread ne peut pas être trouvé:" + ThreadId)); } return get; } / ** * Enregistrez un thread au thread pool * <br> * Groupe de défaut UnknownThreadGroup * * @param Nom du nom de thread * @return * / static public long addThreadModel (name de chaîne) {return addThreadModel (inconnutReadGroup, name); } / ** * Enregistrez un thread au thread pool * <br> * Groupe de défaut UnknownThreadGroup * * @param name ThreadName * @param ThreadCount Threadcount * @return * / static public long addThreadModel (String Name, int ThreadCount); } / ** * Enregistrez un thread avec le pool de threads * * @param des informations de groupement de threads de groupe * @param nom de thread nom * @return * / static public long addThreadModel (groupe threadGroup, nom de chaîne) {return addThreadModel (groupe, nom, 1); } / ** * Enregistrez un thread avec le pool de threads * * @Param Group Thread Grouping Informations * @param name ThreadName * @param ThreadCount ThreadCount * @return * / static public long addThreadModel (groupe threadGroup, nom de chaîne, int threadCount); } / ** * Enregistrez un thread avec le pool de threads * * @param du groupe ThreadGroup Informations * @param nom threadName * @param runnable * @param threadcountre * @return * / static public long addthreadModel (threadGroup Group, name, runnable runnable, int threadCount) {threadModel threadModel = new ThreadModel (groupe, nom, nom, runnable); return addThreadModel (ThreadModel); } / ** * Enregistrez un thread avec le pool de threads * * @param threadModel * / static public long addThreadModel (ThreadModel ThreadModel) {ThreadMap.put (ThreadModel.getId, ThreadModel); return threadModel.getId; } / ** * Ajouter la tâche * * @param threadid * @param tâche * @return * / static public boolean addTask (long threadid, taskevent tâche) {ThreadModel threadModel = getThreadModel (threadId); if (threadModel! = null) {ThreadModel.addtask (tâche); return true; } return false; } / ** * Ajouter la tâche du temporisateur * * @param threadid * @param tâche * @return * / static public boolean addTimertask (long threadId, Timertaskevent task) {ThreadModel threadModel = getThreadModel (threadId); if (threadModel! = null) {ThreadModel.Addtimer (tâche); return true; } return false; } / ** * Ajouter la tâche, ajouter la tâche au thread actuel * * @param tâche * @return * / static public boolean addCurrentThreadTask (taskevent task) {Thread currentThread = Thread.currentThread; if (CurrentThread Instance de ThreadModel.MyThread) {long ThreadId = CurrentThread.getId; ThreadModel ThreadModel = GetThreadModel (ThreadID); if (ThreadModel! = NULL) {ThreadModel.AddTask (tâche); return true; }} return false; } / ** * Ajoutez une tâche de minuterie et ajoutez une tâche au thread actuel * * @param tâche * @return * / static public boolean addCurrentThreadTimerTask (TimertAskevent Task) {Thread CurrentThread = Thread.CurrentThread; if (CurrentThread Instance de ThreadModel.myThread) {long ThreadId = currentThread.getid; ThreadModel ThreadModel = GetThreadModel (ThreadId); if (ThreadModel! = NULL) {ThreadModel.Addtimer (tâche); return true; }} return false; }}
Ensuite, jetons un coup d'œil à l'utilisation
Code d'introduction du thread dans l'article précédent
public static void main (String [] args) lève InterruptedException {// parallélisme de thread, plusieurs threads exécutent plusieurs tâches / fonctions Nouveau thread (new run1) .start; nouveau thread (new run2) .start; } // task1 static class run1 implémente runnable {@Override public void run {// exécuter la tâche 1 run1; // exécuter la tâche 3 run3; }} // task2 static class run2 implémente runnable {@Override public void run {// exécuter la tâche 3 run3; // exécuter la tâche 1 run1; // exécuter la tâche 2 run2; }} // tâche 1 public static void run1 {System.out.println ("run1->" + System.currenttimemillis); } // tâche 2 public static void run2 {System.out.println ("run2->" + system.currentTimeMillis); } // tâche 3 public static void run3 {System.out.println ("run3->" + System.currenttimemillis); }J'ai changé le code en mode
public static void main (String [] args) lance InterruptedException {// threads sont parallèles, plusieurs threads exécutent plusieurs tâches / fonction long test1 = threadpool.addthreadmodel ("test thread-1"); long test2 = threadpool.addThreadModel ("Test Thread-2"); // Ajouter une tâche threadpool.addtask (test1, new run1); Threadpool.addtask (test2, new run2); // Ajouter une tâche de temporisation threadpool.addtimertask (test1, new timerrun1); Threadpool.addtimertask (test2, new timerrun2); } // task1 static class run1 étend taskevent {@Override public void run {// exécuter la tâche 1 run1; // exécuter la tâche 3 run3; }} // tâche1 classe statique Timerrun1 étend TimertaSkevent {public timerrun1 {super (500); // 500ms Unlimited Execution} @Override public void run {// Exécuter la tâche 1 run1; // exécuter la tâche 3 run3; }} // tâche2 classe statique Run2 étend Taskevent {@Override public void run {// Exécuter la tâche 3 run3; // exécuter la tâche 1 run1; // exécuter la tâche 2 run2; }} // tâche2 classe statique Timerrun2 étend TimertaSkevent {public timerrun2 {super (500); // 500ms Exécution Unlimited} @Override public void run {// Exécuter la tâche 3 run3; // Exécuter la tâche 1 run1; // exécuter la tâche 2 Run2; }} // task1 public static void run1 {System.out.println ("run1->" + System.currenttimemillis); } // task2 public static void run2 {System.out.println ("run2->" + System.currenttimemillis); } // tâche 3 public static void run3 {System.out.println ("run3->" + System.currenttimemillis); }Ensuite, jetons un coup d'œil à l'effet d'exécution
Run1-> 1472120543013RUN3-> 1472120543013RUN3-> 1472120543017RUN1-> 1472120543017RUN2-> 14721205 43017RUN1-> 1472120543517RUN3-> 1472120543517RUN2-> 1472120543517RUN1-> 1472120544018RUN3-> 1477 2120544018RUN2-> 1472120544018RUN1-> 1472120544520RUN3-> 1472120544520RUN2-> 1472120544520RUN1 -> 1472120545021RUN3-> 1472120545021RUN2-> 1472120545021RUN1-> 1472120545521RUN3-> 147212055521
Tout est normal;
Ceci est mon modèle de filetage personnalisé;
À ce stade, mon modèle de filetage personnalisé est terminé;
Alors, quels sont les avantages et les inconvénients?
L'avantage est que le contrôle du flux de données est très clair, y compris la situation d'exécution actuelle, ainsi que les threads bloqués et l'exécution du temporisateur des tâches;
Inconvénients, ce modèle de thread personnalisé ne peut toujours pas résoudre le problème de la sécurité des données du thread et de la zone critique, et il doit encore être résolu par des verrous ou d'autres formulaires au moment approprié;
J'espère que les grands dieux indiqueront les lacunes, afin que je puisse les corriger immédiatement.