{"id":98,"date":"2014-12-23T12:32:04","date_gmt":"2014-12-23T12:32:04","guid":{"rendered":"http:\/\/smartfoxserver.com\/blog\/?p=98"},"modified":"2019-09-25T07:11:09","modified_gmt":"2019-09-25T07:11:09","slug":"how-to-schedule-timed-tasks-in-an-extension","status":"publish","type":"post","link":"https:\/\/smartfoxserver.com\/blog\/how-to-schedule-timed-tasks-in-an-extension\/","title":{"rendered":"How to schedule timed tasks in an Extension"},"content":{"rendered":"<p>Often times in the server-side game logic it is necessary to use timers for recurring events that are sent to the clients (e.g. the end of a turn time, npc actions, etc).<\/p>\n<p>A quick solution to this problem is using the <strong>ScheduledThreadPoolExecutor<\/strong> class, provided in the JDK, which offers a convenient task executor backed by a pool of threads. SFS2X already runs its own instance of this Executor (wrapped in a class called <em>TaskScheduler<\/em>).<!--more--><\/p>\n<p>The following snippet of Java code shows how to run a looping task using the SmartFoxServer&#8217;s own\u00a0<strong>TaskScheduler<\/strong>.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class SchedulerTestExtension extends SFSExtension\r\n{\r\n    private class TaskRunner implements Runnable\r\n    {\r\n        private int runningCycles = 0;\r\n\r\n        public void run()\r\n        {\r\n\t\t\ttry\r\n\t\t\t{\r\n            \trunningCycles++;\r\n\t            trace(&quot;Inside the running task. Cycle:  &quot; + runningCycles);\r\n\r\n\t            if (runningCycles &gt;= 10)\r\n\t            {\r\n\t                trace(&quot;Time to stop the task!&quot;);\r\n\t                taskHandle.cancel();\r\n\t            }\r\n\t\t\t}\r\n\t\t\tcatch (Exception e)\r\n\t\t\t{\r\n\t\t\t\t\/\/ Handle exceptions here\r\n\t\t\t}\r\n        }\r\n    }\r\n\r\n    \/\/ Keeps a reference to the task execution\r\n    ScheduledFuture&lt;?&gt; taskHandle;\r\n\r\n    @Override\r\n    public void init()\r\n    {\r\n        SmartFoxServer sfs = SmartFoxServer.getInstance();\r\n\r\n        \/\/ Schedule the task to run every second, with no initial delay\r\n        taskHandle = sfs.getTaskScheduler().scheduleAtFixedRate(new TaskRunner(), 0, 1, TimeUnit.SECONDS);\r\n    }\r\n\r\n    @Override\r\n    public void destroy()\r\n    {\r\n    \tsuper.destroy();\r\n\r\n        if (taskHandle != null)\r\n           taskHandle.cancel();\r\n    }\r\n\r\n}\r\n<\/pre>\n<p>The <strong>scheduleAtFixedRate<\/strong> method takes four arguments:<\/p>\n<ol>\n<li>a <em>Runnable<\/em> object that will execute the Task&#8217;s code;<\/li>\n<li>the initial delay before the execution starts;<\/li>\n<li>the interval at which the task will be executed;<\/li>\n<li>the time unit used to express the time values.<\/li>\n<\/ol>\n<p>The Scheduler also exposes a <strong>schedule<\/strong> method that executes a <em>Runnable<\/em> task once after the specified amount of time. Finally the Scheduler&#8217;s thread pool can be resized on-the-fly at runtime via the <strong>resizeThreadPool()\u00a0<\/strong>method.<\/p>\n<p><strong>IMPORTANT<\/strong>: runtime exceptions occurring inside the run() method <strong>will stop the Task from running<\/strong>. If don&#8217;t want your Task to be interrupted by an expected error make sure to catch any Exception that might occur.<\/p>\n<p>Finally notice how we keep track of the started task via the <strong>taskHandle<\/strong> variable and make sure to stop it when the Extension is removed, via the <strong>destroy()<\/strong> method. This is important to avoid leaking the task in memory.<\/p>\n<div class=\"dottedYellowBox\"><strong>NOTE:<br \/>\n<\/strong>The initial size of the system TaskScheduler&#8217;s thread pool can be adjusted via the <a href=\"http:\/\/docs2x.smartfoxserver.com\/GettingStarted\/admintool-ServerConfigurator\">Server Configurator<\/a> module in the <strong>AdminTool.<\/strong><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Often times in the server-side game logic it is necessary to use timers for recurring events that are sent to the clients (e.g. the end of a turn time, npc actions, etc). A quick solution to this problem is using the ScheduledThreadPoolExecutor class, provided in the JDK, which offers a convenient task executor backed by [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[5],"tags":[7],"_links":{"self":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/98"}],"collection":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/comments?post=98"}],"version-history":[{"count":5,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/98\/revisions"}],"predecessor-version":[{"id":1188,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/posts\/98\/revisions\/1188"}],"wp:attachment":[{"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/media?parent=98"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/categories?post=98"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smartfoxserver.com\/blog\/wp-json\/wp\/v2\/tags?post=98"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}