Tut mir leid wegen der Thread-Nekromantie, aber dieses Problem ist mein LIEBLINGS-Haustierprojekt zum Lernen und Lehren von Parallelitätsmodellen und Frameworks!
Das Ausführen jedes Clients / Mobs in einem eigenen Thread ergibt eine natürliche Unterteilung, aber wie mehrere angemerkt haben, sind Threads teuer, wenn Sie mehr davon verwenden als Sie CPU-Kerne haben. Wenn dies kein zwingender Grund ist, es nicht in Ihrem MUD zu verwenden, ist es dennoch ein guter Grund, einen besseren Weg zu lernen.
Das Ausführen aller Clients in einer einzigen Spielschleife mit fester Zeit und Aktionen, die einige Schleifen umfassen, ist eine bekannte Methode aus der Welt der grafischen Spiele. Es bindet alles auf der Welt an denselben Zeitzyklus, obwohl eine ausreichende Feinkörnung der Schleifen dies maskieren kann. Der Hauptnachteil dieser Methode ist meines Erachtens, dass sie nicht von Natur aus parallelisierbar ist. Jemand bemerkte, dass Sie Threads erstellen können, um das Erstellen / Parsen / Transceiving von E / A, das Ausführen von KI usw. auf andere Threads zu verlagern. Die Parallelisierung der Hauptspiellogik erfordert jedoch eine grundlegende Änderung und viel Arbeit, um die Thread-Sicherheit zu gewährleisten.
Wenn Sie all diese Arbeiten erledigt hätten, hätten Sie wahrscheinlich etwas Ähnliches wie meinen aktuellen Favoriten, das Actor-Modell ( http://en.wikipedia.org/wiki/Actor_model ). Das Actor-Modell ist eine Time-Sharing-Strategie, die ziemlich genau dem entspricht, was Sie mit der One-Thread-per-Client-Idee vorgeschlagen haben. Wenn Sie es verwenden, codieren Sie Ihre "Akteure" wie eigenständige Threads, mit einigen Einschränkungen: Sie müssen ereignisgesteuert sein und können nur durch Weiterleiten von Nachrichten mit dem Rest des Systems kommunizieren (was anders, aber einfach ist). Das ereignisgesteuerte Bit bietet Platz für Ihr wirklich unabhängiges Timing, indem aktorspezifische Ereignisse so geplant werden, dass sie zu bestimmten Zeiten ausgelöst werden, z. B. wenn eine Aktion abgeschlossen ist oder mit einer bestimmten Client-Häufigkeit.
Unter der Haube verwendet die Implementierung eine Warteschlange (oder Warteschlangen) von Nachrichten, die von allen Akteuren generiert werden, und einen Pool von Threads, die Ihrer Anzahl von CPU-Kernen entsprechen. Die Threads ziehen Nachrichten aus den Warteschlangen und rufen die Nachrichtenbehandlungsmethoden des Empfängerakteurs auf, um sie zu verarbeiten. Sie werden im Kontext dieses Akteurs ausgeführt, bis die Nachricht "verarbeitet" wird. Aus Ihrer Sicht erhält jeder Akteur seinen eigenen Thread, wann immer er tatsächlich ausgeführt wird. Aus Sicht des Systems gibt es jedoch nur so viele Threads wie CPUs, um sie auszuführen.
Es gibt einige großartige Actor-Frameworks, nämlich Erlang / OTP und Akka, aber die Grundidee ist so einfach, dass Sie sie in jeder Sprache ohne den zusätzlichen Aufwand eines Frameworks implementieren können.
Der Vollständigkeit halber ist das Actor-Modell eigentlich nur die Kombination aus Nachrichtenübermittlung für die Thread-Sicherheit, ereignisgesteuerter Programmierung für die Parallelität und einem Thread-Dispatching-Mechanismus. Wenn Sie die Thread-Dispatch-Bits entfernen würden, hätten Sie ein "reaktives" System, das derzeit für die Skalierbarkeit im Allgemeinen sehr beliebt ist (siehe http://www.reactivemanifesto.org/ ). Sie können die Ausführung dann mehreren Computern in einer Cloud oder was auch immer zuordnen ... Sie haben die Idee ... was alles bedeutet, dass Ihr MUD-Programmierprojekt Ihnen möglicherweise marktfähige Programmierkenntnisse vermittelt. Hurra!