Solved Sync and aSync Schedule Question.

Discussion in 'Plugin Development' started by iZanax, Oct 3, 2012.

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


    I've made a 15 minute timer, but it seems to take longer than 15 minutes.
    Some my question is, what is the difference between Sync and aSync schedules.
    I've red something that aSync schedules can't use the Bukkit API or its thread unsafe if u call the Bukkit API.

    Methode: Timer
                pl.getServer().getScheduler().scheduleSyncDelayedTask(pl, new Runnable() { public void run() {
    pl.timer.get(1).setTime(pl.timer.get(timer).getTime() - 1);
    // A*
    }}, 1200); // per minute 1200ticks
    • Could I use aSync in this case? to be sure its really 15minutes?
    • And what if there stand at A* player.teleport(new Location(x,x,x,x));
      Should that give problems?
    I hope the answers will clear up, when to use aSync and when Sync.
  2. Offline


    Your timer is probably taking longer than 15 minutes because sync tasks are scheduled to execute after a certain number of ticks have elapsed, and the (often incorrect) assumption is made that 20 ticks == 1 second. In fact, the ticks/second rate is variable depending on how much load the server on which the plugin is being run is experiencing.

    Async tasks are run in separate threads, so only those Bukkit API methods that are specifically designated as thread-safe may be called. For more information regarding async tasks and which Bukkit methods are thread-safe, check out this Bukkit wiki article.

    Plugins like LagMeter and Essentials use async tasks for timers that determine how much real-world time has actually elapsed. I'd take a look at the LagMeter repository for an example of this sort of thing in action.

    Edit: Much more comprehensive answer right below mine, look there for a proper explanation of all the related concepts ^^
  3. Offline


    The only difference between "sync" and "async" tasks:
    - sync tasks are executed by the main server thread (like everything else)
    - async tasks are executed by a dedicated thread

    What is a "thread"? Basically, it's a worker that executes code one after another. If 2 of them run, the CPU lets them work "at the same time" (hops from one to another, or uses its multiple cores).
    The problem is that if you use async with bukkit, your task will be one of these "parallel jobs", not being in sync with the normal server.
    So as soon as your parallel worker starts doing something (teleporting the player), it can do that at ANY unpredictable point of time.
    It can cut in right at a point whe the main server does something with the player's location, possibly resulting in some corrupt calculations. For teleportation, it also launche a teleport event - also in your custom thread, that another plugin might use to do even more complex stuff.
    This can eventuall crash the server or corrupt the world or cause other weird glitches, if it happens to cut in at an inconvenient time.

    That's what "concurrency" and "thread safety" is about. To circumvent this problem, there is a concept called synchronization. But most of the minecraft server / bukkit API doesn't use that (for good reasons), so it's not possible to do most of the stuff asynchronously.

    In your case, there's absolutely no reason to do so, though. It will not fix your timing problem (I'll get to that i a second). It's only useful when the task itself has some heavy duty to do - something that takes very long but doesn't directly need server interaction.
    Examples would be HTTP requests, database connections, enourmous mathematical calculations, etc.

    In your case, you're not doing anything heavy-weight in there, so it's unreasonable to do it asyncly.

    Now why is it not taking exactly 15 minutes? Because it is scheduled in server ticks. You know there should be 20 a second, but in most cases it's a little less - because of lag.
    So when the server constantly runs on 19 ticks/second, 1200 ticks suddenly start to take longer than expected.
    This will happen both with sync and async tasks, so that's not the solution.

    I suggest you use the system time:
    • Store the time you want the task to execute
    • Have a repeating task that fires every x ticks (depending on the accuracy you need, I'd suggest something between every 20-1200 ticks)
    • check the current time in that task and compare it with the stored one
    • if it's after that, do your work, otherwise do nothing

    I would completely keep your hands of async stuff if you've never worked with threads. There's really no need for it in this situation. Your repeating task above works fine when it's synchronous.
  4. Offline


    Okay I understand now, thanks a lot.
Thread Status:
Not open for further replies.

Share This Page