0
\$\begingroup\$

So here is the thing: I have made a thread for each generator an outpost has. We have a total of 6 outposts , 5 generators each. 3 teams, engineers can only repair generators and prevent their overload. In order to make the whole generator logic I use threads. If the thread gets interrupted it means that the generator got prevented from being destroyed , if the thread is finished normally , the generator got destroyed and if the generator is destroyed an engineer can repair them. Is there any way of avoiding threads because in spite of high cpu usage there are also other thread issues.

The same thing happens with the shield regeneration of each player. I'll just post the code for this one:

public static void startRegenerate(final Player p){

    if(already_regenerating_arraylist.contains(p.getId())){
        return;
    }

    final int previous_shield_lvl = p.getShieldLevel();
    final int previous_hp_lvl = (int) p.getHealth();

    Thread reg = new Thread(){  

        @Override
        public void run(){

            already_regenerating_arraylist.add(p.getUniqueId());
            try {
                sleep(3000);
            } catch (InterruptedException e1) {
            }

            for(;;){                            

                if(p.getShieldLevel() >= 20){
                    p.setShieldLevel(20);
                    already_regenerating_arraylist.remove(p.getUniqueId());
                    break;
                }

                if(p.getHealth() < previous_hp_lvl || p.getShieldLevel() < previous_shield_lvl){
                    already_regenerating_arraylist.remove(p.getUniqueId());
                    break;
                }

                p.setFoodLevel(p.getFoodLevel() + 6);               

                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                }
            }

        }

    };

    reg.start();
}

After having more than 50 players stuff stop working (lag , etc...)

\$\endgroup\$
  • 1
    \$\begingroup\$ What is the question? \$\endgroup\$ – Katu Jul 5 '14 at 10:56
4
\$\begingroup\$

Rule number one of multithreading: avoid it. You might think: "Well, there are things in my game which are supposed to happen simultaneously. Wouldn't it be much more intuitive when each thing happens in its own thread?" No, it's not. Using multithreading makes your program magnitudes more complex. You have no control over how much CPU time the operating system gives to each of your threads and when exactly it switches between them, so they will become out of sync unless you manually synchronize them by making them wait for each other to finish. This introduces very hard to reproduce bugs due to race conditions and deadlocks. Sure, there are language features like synchronized to avoid some of them, but these have pitfalls on their own and are easy to forget.

The only argument ever for using more than one thread is performance.

Use threading when you have some calculation which is so CPU-intense that you need more than one core. But in that case don't use more threads than the machine has (currently idle) CPU cores and make sure each thread is able to do a lot of work before being forced to yield or wait for another thread, or you will gain nothing except burdening the OS with additional thread context switches. That's likely what slows down your application.

Another reason to use threading is when you have any network, database or file IO and don't want your application to become unresponsive in the meantime. However, in that case most environments should provide an asynchronous API which does the dirty multithreading stuff for you. In Java, thats Non-blocking IO.

OK, so how else could you structure your application?

You could have a standard game loop.

while game is running
     render a frame
     check time elapsed since last gamestate update
     update gamestate taking the elapsed time into account

give each object in your game an update() function and call that function of each object in a for-loop in your global update gamestate function.

There are two different approaches how to take the elapsed time into account. Either the delta-t model where you pass the difference between real-world time and processed time to the update-function and take it into account for all calculations, or the tick-model where you agree on the internal ticks-per-second rate with which your game logic works (usually 100), check how many ticks your simulation is behind real-time, and call the update-function that many times.

Which one is the better method depends on the game and your personal preference. I personally prefer the tick-method because it is a lot easier to write the update-functions when you don't have to take the delta-t factor into account for everything, but the delta-t method can sometimes (not always!) be a bit faster.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks , I need to get used to all this update thing.... \$\endgroup\$ – user3029101 Jul 5 '14 at 21:23
1
\$\begingroup\$

Don't use threads for this. Change "run" method to "update" and just loop through all generators in your mainloop and call "update" for those. I find your logic hard to understand and code hard to debug. This is just my opinion, but threads are not good for this kind of situations. You even have thread sleep in there, so it actually is not that time critical loop.

So, instead of creating thread for that, create update method that does what ever needs to be done and call it from mainloop.

| improve this answer | |
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.