Solved Make task wait until previous task is finished

Discussion in 'Plugin Development' started by kabbage, Mar 2, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    kabbage

    Alright, so I have a class that implements Runnable and is always called asynchronously.
    In that class's run method, I then run several synchronous tasks. The problem I'm facing is that the tasks aren't being run in order, some of them take longer than others, so the shorter ones get finished first. How would I make it so one task won't start until the previous task has been finished?

    Here's a pseudo example of what I'm doing if my explanation isn't clear.
    Code:
    public class AsyncTask implements Runnable {
            @Override
            public void run() {
                Bukkit.getScheduler().runTask(Plugin.getInstance(), new Task1());
                Bukkit.getScheduler().runTask(Plugin.getInstance(), new Task2());
                Bukkit.getScheduler().runTask(Plugin.getInstance(), new Task3());
                Bukkit.getScheduler().runTask(Plugin.getInstance(), new Task4());
                Bukkit.getScheduler().runTask(Plugin.getInstance(), new Task5());
            }
        }
     
  2. Of course they run at diferent speeds because they're diferent threads.

    The easiest way would be to just use a single task and do stuff there in order.

    Or you could use wait/notify methods but I don't really understand them so I can't explain, google it :p
     
  3. Offline

    Tirelessly

    Depending on how you implement it you can use Thread.join, probably. Digi wait and notify are for a different purpose.
     
  4. Offline

    kabbage

    Can't run them in a single task.
    How would I do that?
     
  5. Offline

    Tirelessly

    Code:java
    1.  
    2. public class AsyncTask implements Runnable {
    3. @Override public void run() {
    4. BukkitTask t = Bukkit.getScheduler().runTask(Plugin.getInstance(), new Task1());
    5. t.join();
    6. BukkitTask t2 = Bukkit.getScheduler().runTask(Plugin.getInstance(), new Task2());
    7. t2.join();
    8. etc. } }
    9.  

    That will make the first one run, then it'll wait at t.join() until it's finished, then the second will run, wait at t2.join() until it's finished, etc..
     
  6. Why can't you run them in a single task ?
    If you have to wait between them then use Thread.sleep();

    Code:
    new BukkitRunnable()
    {
      public void run()
      {
         new Task1(); // just create the instance, no actual runnable
         Thread.sleep(100); // wait 100ms
         new Task2();
         // etc...
      }
    }.runTaskAsynchronously(plugin);
    And that will guarantee ordered execution :p
    If you really need separate tasks (and I'm curious why :p) you can use @Tirelessly's way but mind that he's calling the tasks in the main thread.

    And I hope you're aware that you should not use Bukkit API methods inside ASync tasks.
     
  7. Offline

    kabbage

    Tirelessly
    Bukkit Tasks don't seem to have a join method
    Digi
    I can't run them all in one task because their's a bunch of calculations are going on between each task. They are very server intensive, so they need to be run asynchronously as to not interfere with the rest of the server too badly. The tasks in between have to be synchronous because they make calls to the Bukkit API.

    Thread.Sleep would technically work, but it wouldn't be very clean or fast, as I'd have to make the value large enough as to guarantee their are no overlaps.
     
  8. Offline

    Tirelessly

    That's probably because they aren't real threads.. Not sure then. How about at the start of the task you set a boolean to true (make it volatile) and at the end you make the boolean false. Then in between each of the tasks do something like "while(waiting){}"
     
    kabbage likes this.
  9. Offline

    FalseVacuum

    Do you need to use the Bukkit task system? In any case, try something like this

    Code:
    AtomicInteger aint = new AtomicInteger(0)
    startMyFirstTask(aint)
    startMySecondTask(aint)
     
    ... //Each task should call getAndIncrement() when done
     
    if(aint.get() == numberOfTasks) //all tasks done
    else //continue on with life
    
    You have to havetohavetohaveto use Atomic. Otherwise, you end up with concurrency problems and the whole world blows up. No joke. Or you get eaten by velociraptors.

    See: http://en.wikipedia.org/wiki/Race_condition#Example
     
  10. Offline

    Tirelessly

    He needs to use bukkit tasks because they need to be synchronous.
     
  11. Offline

    FalseVacuum

    "They are very server intensive, so they need to be run asynchronously"

    I don't think he needs synchronous. But I never said not to use Bukkit tasks. My proposed solution would work with Bukkit tasks or otherwise.
     
  12. Offline

    Tirelessly

    Not defending his methods, just saying..
     
  13. Offline

    kabbage

    That works perfectly, thanks!

    I do need synchronous tasks, as I make several calls to the Bukkit API. Unless there's some way to make calls to the Bukkit API asynchronously I'm unaware of...
     
  14. Offline

    Tirelessly

    There isn't. Inside that while loop put a Thread.sleep(x) with x being like 50ms - 5000ms.
     
  15. Offline

    kabbage

    Done. Is that just to improve performance, or will things break without it?
     
  16. Offline

    Tirelessly

    That's just to improve performance.
     
    kabbage likes this.
  17. So let me get this straight, you need to do stuff in the main thread in between async tasks and you need them ordered ?
    If that's the case then make a chain: if you have a strict order of execution which won't change and you already have separate classes for each math-intensive thing, then at the end of each run() create a sync task that calls your main thread stuff then calls the next async task, the same for other classes, and you have a big chain of sync/async tasks that run in order.
    With this method it is guaranteed that you won't get any gaps, which you get with while() and sleep() :p
     
  18. Offline

    kabbage

    Digi
    I'm not doing stuff in the main thread between async tasks, I'm doing stuff in one, huge async task.

    I could separate them all up into separate classes, but it seems a bit unnecessary, as sleep()ing works fine.
     
  19. If you're doing it in one single async task then why do you even use sleep ? :confused: ...

    Only explication I can think of is that you're starting other async tasks from within that async task, which would be very pointless.
     
Thread Status:
Not open for further replies.

Share This Page