1

I am developing a text-based game, MUD. I have the base functions of the program ready, and now I would like to allow to connect more than one client at a time. I plan to use threads to accomplish that.

In my game I need to store information such as current position or health points for each player. I could hold it in the database, but as it will change very quick, sometimes every second, the use of database would be inefficient (am I right?).

My question is: can threads behave as "sessions", ie hold some data unique to each user?

If yes, could you direct me to some resources that I could use to help me understand how it works?

If no, what do you suggest? Is database a good option or would you recommend something else?

Cheers, Eleeist

Eleeist
  • 6,891
  • 10
  • 50
  • 77

5 Answers5

5

Yes, they can, but this is a mind-bogglingly stupid way to do things. For one thing, it permanently locks you into a "one thread per client" model. For another thing, it makes it difficult (maybe even impossible) to implement interactions between users, which I'm sure your MUD has.

Instead, have a collection of some kind that stores your users, with data on each user. Save persistent data to the database, but you don't need to update ephemeral data on every change.

One way to handle this is to have a "changed" boolean in each user. When you make a critical change to a user, write them to the database immediately. But if it's a routine, non-critical change, just set the "changed" flag. Then have a thread come along every once in a while and write out changed users to the database (and clear the "changed" flag).

Use appropriate synchronization, of course!

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • I have never used collections before, so I will have to learn some new things in order to try it out. Thanks for insight :). – Eleeist Jan 25 '12 at 20:36
  • You've never used a linked list, map, hash table, or array? – David Schwartz Jan 25 '12 at 22:00
  • I have used arrays. So you suggest to put each user that connects into a collection? But won't I need a separate thread for each one (user)? Sorry I just don't get the logic behind this :( – Eleeist Jan 25 '12 at 22:22
  • Put whatever information you need about each user into a collection. Whenever you need information about a user, get it from the collection. Since any thread can access the collection and get information about any user, there is no reason you need a separate thread for each one. – David Schwartz Jan 25 '12 at 23:48
  • How can I put a information about a user that connects into a collection? – Eleeist Jan 28 '12 at 20:34
  • That's a pretty basic programming question. Start with the [official documentation](http://java.sun.com/developer/onlineTraining/collections/Collection.html). – David Schwartz Jan 28 '12 at 21:42
4

A Thread per connection / user session won't scale. You can only have N number of threads active where N is equal to the number of physical cores / processors your machine has. You are also limited by the amount of memory in your machine for how many threads you can create a time, some operating systems just put arbitrary limits as well.

There is nothing magical about Threads in handling multiple clients. They will just make your code more complicated and less deterministic and thus harder to reason about what is actually happening when you start hunting logic errors.

A Thread per connection / user session would be an anti-pattern!

Threads should be stateless workers that pull things off concurrent queues and process the data.

Look at concurrent maps for caching ( or use some appropriate caching solution ) and process them and then do something else. See java.util.concurrent for all the primitive classes you need to implement something correctly.

  • `A Thread per connection / user won't scale`.Why not?What do you suggest?Event based handling of incoming connections? – Cratylus Jan 25 '12 at 21:13
2

Instead of worrying about threads and thread-safety, I'd use an in-memory SQL database like HSQLDB to store session information. Among other benefits, if your MUD turns out to be the next Angry Birds, you could more easily scale the thing up.

1

Definitely you can use threads as sessions. But it's a bit off the mark.

The main point of threads is the ability of concurrent, asynchronous execution. Most probably, you don't want events received from your MUD clients to happen in an parallel, uncontrolled order.

To ensure consistency of the world I'd use an in-memory database to store the game world. I'd serialize updates to it, or at least some updates to it. Imagine two players in parallel hitting a monster with HP 100. Each deals 100 damage. If you don't serialize the updates, you could end up giving credit for 100 damage to both players. Imagine two players simultaneously taking loot from the monster. Without proper serialization they could end up each with their own copy of the loot.

Threads, on the other hand, are good for asynchronous communication with clients. Use threads for that, unless something else (like a web server) does that for you already.

9000
  • 39,899
  • 9
  • 66
  • 104
  • What do you mean by in-memory database? – Eleeist Jan 25 '12 at 20:40
  • Something [like this](https://www.google.com/search?q=in-memory+database+java) :) Something smarter than just a list of game objects. In a complex game world, you probably will need to make various queries related to its state and would like to enforce some constraints that you can't express through Java's limited type system. – 9000 Jan 25 '12 at 20:51
0

ThreadLocal is your friend! :)

http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html

ThreadLocal provides storage on the Thread itself. So the exact same call from 2 different threads will return/store different data.

The biggest danger is having a leak between Threads. You would have to be absolutely sure that if a different user used a Thread that someone else used, you would reset/clear the data.

rfeak
  • 8,124
  • 29
  • 28
  • Thanks, I will definitely take a look that ThreadLocal :). I plan to store the data in a thread as long as the user is connected to the server. When he disconnects, I would like to save all the data from the thread into database, so when he reconnects he will be able to play from when he left off. Does it sound like a achievable idea? – Eleeist Jan 25 '12 at 20:27
  • Yes. Just be VERY sure that when someone connects, you load their data, and when they disconnect you clean out the ThreadLocal so that you don't have cross talk. That being said, I would heed some of the other answers here. I'm explaining how a tool works for what you asked for. Whether or not it's wise to use this tool is up to you. Often what would really be in the Thread local would just be an ID. Then you can pull the data from the DB, or a local cache to avoid heavy DB usage. – rfeak Jan 25 '12 at 20:29