Thread question

Post here your questions about SFS2X. Here we discuss all server-side matters. For client API questions see the dedicated forums.

Moderators: Lapo, Bax

User avatar
gabrielvpy
Posts: 54
Joined: 23 Jul 2015, 20:18

Thread question

Postby gabrielvpy » 22 Oct 2015, 18:02

Hello, I have a question. I have the following structure to process when a player uses an ability in my game:
The client sends the request to execute to the server, the ability handler sends it to the world simulator, the world simulator sends it to a the character class and it responds with the damage to the world simulator which then uses the extension to send the clients the damage. Same thing happens to sync up the animation.
Now I'm implementing a new ability that keeps doing damage. I need to tell the clients it began with an initial damage but then I need my thread to continue running. My question is, how can I create a new thread that keeps running even if the one that handle the request is done? I don't have access to the world simulator from my character class and don't want to put it there just for this ability.
We made an awesome GPS - MOBA.
Try it out here: Get Fhacktions
User avatar
Lapo
Site Admin
Posts: 19988
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Thread question

Postby Lapo » 23 Oct 2015, 07:54

Hi,
you can use scheduled tasks. A task is not a thread and it is more efficient because it reuses threads from a thread pool.
See here:
http://docs2x.smartfoxserver.com/Gettin ... wtos#item7

The task will run every X seconds, milliseconds, or whatever you specify and it will keep generating damage on every cycle.

You can use the system's Scheduler or, if you are running hundreds of tasks, you could create your own Scheduler and keep it in the main Extension class.

Makes sense?
Lapo
--
gotoAndPlay()
...addicted to flash games
User avatar
gabrielvpy
Posts: 54
Joined: 23 Jul 2015, 20:18

Re: Thread question

Postby gabrielvpy » 23 Oct 2015, 12:20

I'm familiar with the scheduler but I don't want to use it because I won't need i most of the time. I don't want to have a task asking every second if he need to do something if it will have work just 5% of the time at most. I mean, wouldn't that be a waste of resource? If I don't have another option I'll obviously just do that. But I want to know for certain that I don't have another way to do that.
We made an awesome GPS - MOBA.
Try it out here: Get Fhacktions
User avatar
Lapo
Site Admin
Posts: 19988
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Thread question

Postby Lapo » 23 Oct 2015, 14:18

It's not waste of resources, you can rest assured, but more importantly can't you set the frequency at which the task should run more precisely?
Why should it run every second if it's meant to be execute every once in a while? I am not sure I fully understand your use case.

In any case running tasks in a Scheduler is much, much better than manually creating and destroying your own threads.

cheers

p.s. = Sorry I didn't realize this was posted under SFS PRO, and not SFS2X. In any case the solution applies for both, even though my first answer was assuming you were using SFS2X.

If you're using the PRO I'd recommend using the ScheduledThreadPoolExecutor from the JDK:
https://docs.oracle.com/javase/7/docs/a ... cutor.html

In SFS2X we expose a TaskScheduler object which wraps the above and it's a bit more convenient to use, especially for beginners.
Lapo

--

gotoAndPlay()

...addicted to flash games
User avatar
gabrielvpy
Posts: 54
Joined: 23 Jul 2015, 20:18

Re: Thread question

Postby gabrielvpy » 23 Oct 2015, 14:42

Oh, I'm sorry. I meant to post it SFS2X. Can you move it please?
I guess I didn't explain myself very well. I have an ability that has to respond the client informing the inicial amount of damage done but also needs to keep taking life from the character that took the punch. I wanna do that by having my extension working as a usual thread that creates another thread that keeps doing the damage. This ability won't be used that often so I don't want a Task scheduled just for this ability.
We made an awesome GPS - MOBA.
Try it out here: Get Fhacktions
User avatar
Lapo
Site Admin
Posts: 19988
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Thread question

Postby Lapo » 23 Oct 2015, 15:04

I have moved the discussion, no problem.

Well then, if you don't want to use the Scheduler I think the problem is already solved :)
Lapo

--

gotoAndPlay()

...addicted to flash games
User avatar
gabrielvpy
Posts: 54
Joined: 23 Jul 2015, 20:18

Re: Thread question

Postby gabrielvpy » 23 Oct 2015, 15:57

I'm gonna try to explain myself again. I need thread A to do something and create thread B that will do some other thing. When A is done it can die but B needs to keep running. How do I do that?
We made an awesome GPS - MOBA.
Try it out here: Get Fhacktions
User avatar
Lapo
Site Admin
Posts: 19988
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Thread question

Postby Lapo » 23 Oct 2015, 16:13

I think I've already replied to that, let me clarify in the light of your last request:

Thread A is the thread from the Extension Controller executing your custom action.
Thread B is the thread from the Scheduler executing the repetitive task (cause damage).

So Thread A does its job, creates the Task and returns. As you are asking.

The difference with creating a new Thread B is that:

1) you're using a thread pool, which is more efficient and doesn't require creating and managing threads manually
2) the task can run once, twice, 30 times, 100 times... for as long as you need it, it will only occupy one thread for the short time of executing your task (e.g. nanoseconds) and release it right after

The solution is more scalable and efficient than creating and managing threads manually. Given the advances that Java has done since version 5 in terms of Executors and thread pools I don't see the need for manually working with threads any longer.

cheers
Lapo

--

gotoAndPlay()

...addicted to flash games
User avatar
gabrielvpy
Posts: 54
Joined: 23 Jul 2015, 20:18

Re: Thread question

Postby gabrielvpy » 23 Oct 2015, 16:27

Now I understand what you mean. But how do I call the schedule to just run once?
This is my current setup. My scheduler restores shields. Do I use a new scheduler?

Code: Select all

private class TaskRunner implements Runnable
{
   private World world;
   
   TaskRunner(World world){
      this.world = world;
   }
     
    public void run()
    {
       List<Avatar> players = this.world.getPlayers();
       for (int i = 0; i < players.size(); i++) {
         if(players.get(i).restaurarEscudo()) clientUpdateHealth(players.get(i));
      }
    }
}
 
// Keeps a reference to the task execution
private ScheduledFuture<?> taskHandle;
   
   @Override
   public void init()
   {
      trace("Batalla Extension -- started");
      world = new World(this);  // Creating the world model
      
      addRequestHandler("sM", SpawnMeHandler.class);
                ....//other handlers
      SmartFoxServer sfs = SmartFoxServer.getInstance();
                taskHandle = sfs.getTaskScheduler().scheduleAtFixedRate(new TaskRunner(world), 0, 1, TimeUnit.SECONDS);
      
   }
   
   @Override
   public void destroy()
   {
       super.destroy();
       taskHandle.cancel(true);
       trace("Batalla Extension -- stopped");
   }
We made an awesome GPS - MOBA.
Try it out here: Get Fhacktions
User avatar
Lapo
Site Admin
Posts: 19988
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Thread question

Postby Lapo » 23 Oct 2015, 16:41

There are two main methods in the Scheduler :

.schedule(...)
.scheduleAtFixedRate(...)

The former is what you need, if you want to run the task once and be done with it.

Do I use a new scheduler?

Not necessarily. SmartFoxServer already runs a global scheduler and you can use it for your own tasks too.

Code: Select all

SmartFoxServer.getInstance().getTaskScheduler()


If you plan to run hundreds and hundreds of tasks you can reconfigure the number of threads it uses from the AdminTool > Server Settings. Otherwise you're good to go.
Lapo

--

gotoAndPlay()

...addicted to flash games
User avatar
gabrielvpy
Posts: 54
Joined: 23 Jul 2015, 20:18

Re: Thread question

Postby gabrielvpy » 30 Dec 2015, 19:03

I've been using the Task Scheduler in it works great. But now I have a problem. When I stop my room extension I use the taskHandleTorreta.cancel(true) to cancel the threads but keep running. Why is that happening?
We made an awesome GPS - MOBA.
Try it out here: Get Fhacktions
User avatar
Lapo
Site Admin
Posts: 19988
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Thread question

Postby Lapo » 31 Dec 2015, 08:33

Hi,
you need to cancel all tasks you have started. Other than that it should work. Do you keep a reference to every started task?

cheers.
Lapo

--

gotoAndPlay()

...addicted to flash games
User avatar
gabrielvpy
Posts: 54
Joined: 23 Jul 2015, 20:18

Re: Thread question

Postby gabrielvpy » 31 Dec 2015, 12:10

Yes I do. And that's the weird part. This is my setting. I have a few turret in my world and each turret has a "private ScheduledFuture<?> taskHandleTorreta" that is in charge of controlling who's near to attack. so when someone destroys it I can just kill that task. Also when the game is over I cancel every turret's task. But it stays alive. I have them print every once in a while a message to know if they are still working. What could I be doing wrong?
We made an awesome GPS - MOBA.
Try it out here: Get Fhacktions
User avatar
Lapo
Site Admin
Posts: 19988
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Thread question

Postby Lapo » 02 Jan 2016, 11:21

I have no idea, I suspect you need to debug your code better.
Maybe you should store all those tasks in a List so that when the game is over you can cycle through the list and kill all of them.

cheers
Lapo

--

gotoAndPlay()

...addicted to flash games
User avatar
gabrielvpy
Posts: 54
Joined: 23 Jul 2015, 20:18

Re: Thread question

Postby gabrielvpy » 04 Jan 2016, 19:39

I just tried this. And it didn't work. I gotta be doing something wrong here. This is my code:

ThreadTester.java

Code: Select all

public class ThreadTester implements Runnable{
   
   public ThreadTester(){
      System.out.println("ThreadTester beggins working");
   }
     
    public void run()
    {
      while (true) {
         System.out.println("ThreadTester is still alive");
         try {
            Thread.sleep(250);
         } catch (InterruptedException e) {
            System.out.println("I was interrupted!!!!!!!!");
            System.out.println("Thread.currentThread().isInterrupted(): "+ Thread.currentThread().isInterrupted());
            System.out.println("Thread.currentThread().isAlive(): " + Thread.currentThread().isAlive());
            e.printStackTrace();
         }
      }
    }
}


World.java

Code: Select all

...
        private ScheduledFuture<?> threadTestertask;

   public World(BatallaExtension extension) {
      this.extension = extension;
      threadTestertask = getExtension().callHiloIndependiente(new ThreadTester());
      ...
   }
        ...

        public boolean addOrRespawnPlayer(User user) {
         Avatar player = getPlayer(user);
         if (player == null) {
            System.out.println("empiezo a inicializar el avatar de : " + user.getName());
            if(user.getName().equalsIgnoreCase("vicente")){
               System.out.println("now I'll kill my Threadtest");
               threadTestertask.cancel(true);
            }
        ....


in my extension I have this method:

Code: Select all

public ScheduledFuture<?> callHiloIndependiente(Runnable task){
      return SmartFoxServer.getInstance().getTaskScheduler().schedule(task, 0, TimeUnit.SECONDS);
   }


Let me explain how I want to make it work.
When my world is initialized I create a task with the runnable ThreasTester class that is supposed to run endlessly. But when the user named "vicente" wants to spawn I cancel the task. But it keeps running. This is the output I get:

ThreadTester is still alive
ThreadTester is still alive
ThreadTester is still alive
ThreadTester is still alive
empiezo a inicializar el avatar de : vicente
now I'll kill my Threadtest
I was interrupted!!!!!!!!
Thread.currentThread().isInterrupted(): false
Thread.currentThread().isAlive(): true
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.fhacktions.batalla.runnable.ThreadTester.run(ThreadTester.java:15)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
ThreadTester is still alive
ThreadTester is still alive
ThreadTester is still alive


What am I doing wrong?
We made an awesome GPS - MOBA.
Try it out here: Get Fhacktions

Return to “SFS2X Questions”

Who is online

Users browsing this forum: No registered users and 2 guests