<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://mineplugin.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=A390807154</id>
	<title>Minecraft插件百科 - 用户贡献 [zh-cn]</title>
	<link rel="self" type="application/atom+xml" href="https://mineplugin.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=A390807154"/>
	<link rel="alternate" type="text/html" href="https://mineplugin.org/%E7%89%B9%E6%AE%8A:%E7%94%A8%E6%88%B7%E8%B4%A1%E7%8C%AE/A390807154"/>
	<updated>2026-06-17T14:57:42Z</updated>
	<subtitle>用户贡献</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://mineplugin.org/index.php?title=Bukkit/%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E6%95%99%E7%A8%8B/%E5%AE%9A%E6%97%B6%E5%99%A8%E7%BC%96%E7%A8%8B&amp;diff=2954</id>
		<title>Bukkit/插件开发教程/定时器编程</title>
		<link rel="alternate" type="text/html" href="https://mineplugin.org/index.php?title=Bukkit/%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E6%95%99%E7%A8%8B/%E5%AE%9A%E6%97%B6%E5%99%A8%E7%BC%96%E7%A8%8B&amp;diff=2954"/>
		<updated>2016-03-15T11:25:49Z</updated>

		<summary type="html">&lt;p&gt;A390807154：​/* BukkitRunnable */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial will guide you in using the scheduler provided by bukkit. It will allow you to defer the execution of code to a later time. This is not the same as registering a [http://jd.bukkit.org/apidocs/index.html?org/bukkit/event/Listener.html Listener], a block of code which is executed in response to an [http://wiki.bukkit.org/Event_API_Reference event] in the game. Blocks of code may also be scheduled to be executed repeatedly at a fixed interval, with or without a delay. They will continue to execute until completed, or canceled, or your plugin is disabled.&lt;br /&gt;
&lt;br /&gt;
When using [[#BukkitRunnable|BukkitRunnable]], with a separate class, scheduling work occurs in two steps for the programmer.&lt;br /&gt;
# Define the work to be done, see the section [[#Defining_work|Defining Work]]&lt;br /&gt;
# Notify Bukkit when the work should be executed, see the section [[#Scheduling_Work|Scheduling Work]]&lt;br /&gt;
&lt;br /&gt;
Alternatively, work can be scheduled directly with the scheduler, this also occurs in two steps for the programmer.&lt;br /&gt;
# Define the work to be done, in a Runnable or Callable&lt;br /&gt;
# Then directly scheduling the work with the Bukkit Scheduler, see the section [[#BukkitScheduler|BukkitScheduler]]&lt;br /&gt;
&lt;br /&gt;
= BukkitRunnable =&lt;br /&gt;
[http://jd.bukkit.org/apidocs/index.html?org/bukkit/scheduler/BukkitRunnable.html BukkitRunnable] 实现了[http://docs.oracle.com/javase/6/docs/api/index.html?java/lang/Runnable.html Runnable] 的抽象. 它还提供一个Runnable没有的功能, BukkitRunnables 可以安排和取消他自己的执行. 然而, 如果BukkitRunnables 没有被安排执行, 它也不能取消运行自身. BukkitRunnables 不是定时器, 没有任何定时器的逻辑功能,而且创建并不复杂. 插件应该更常使用BukkitRunnables 并且直接调用run()方法来直接调用 Runnable 和 BukkitScheduler.&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;更多关于 BukkitRunnable 的信息, 请查看 [http://jd.bukkit.org/apidocs/index.html?org/bukkit/scheduler/BukkitRunnable.html BukkitRunnable JavaDocs]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== 定义工作 ==&lt;br /&gt;
插件首先得完成t [http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html extend] [http://jd.bukkit.org/apidocs/index.html?org/bukkit/scheduler/BukkitRunnable.html BukkitRunnable] 的定义工作. 换句话说, 定义一个你想要定时执行的运行方法.&lt;br /&gt;
&lt;br /&gt;
=== 基本例子 ===&lt;br /&gt;
这是可被定时的任务示例.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;source lang=java&amp;gt;import org.bukkit.Bukkit;&lt;br /&gt;
import org.bukkit.plugin.java.JavaPlugin;&lt;br /&gt;
import org.bukkit.scheduler.BukkitRunnable;&lt;br /&gt;
&lt;br /&gt;
public class ExampleTask extends BukkitRunnable {&lt;br /&gt;
&lt;br /&gt;
    private final JavaPlugin plugin;&lt;br /&gt;
&lt;br /&gt;
    public ExampleTask(JavaPlugin plugin) {&lt;br /&gt;
        this.plugin = plugin;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void run() {&lt;br /&gt;
        // 你需要在运行的时候执行的内容放这&lt;br /&gt;
        plugin.getServer().broadcastMessage(&amp;quot;Welcome to Bukkit! Remember to read the documentation!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&amp;lt;/source&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 自我取消例子 ===&lt;br /&gt;
这是一个运行数次后自我取消的例子&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;import org.bukkit.plugin.java.JavaPlugin;&lt;br /&gt;
import org.bukkit.scheduler.BukkitRunnable;&lt;br /&gt;
&lt;br /&gt;
public class ExampleSelfCancelingTask extends BukkitRunnable {&lt;br /&gt;
&lt;br /&gt;
    private final JavaPlugin plugin;&lt;br /&gt;
    &lt;br /&gt;
    private int counter;&lt;br /&gt;
&lt;br /&gt;
    public ExampleSelfCancelingTask(JavaPlugin plugin, int counter) {&lt;br /&gt;
        this.plugin = plugin;&lt;br /&gt;
        if (counter &amp;lt; 1) {&lt;br /&gt;
            throw new IllegalArgumentException(&amp;quot;counter must be greater than 1&amp;quot;);&lt;br /&gt;
        } else {&lt;br /&gt;
            this.counter = counter;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void run() {&lt;br /&gt;
        // 你需要在运行的时候执行的内容放这&lt;br /&gt;
        if (counter &amp;gt; 0) { &lt;br /&gt;
            plugin.getServer().broadcastMessage(&amp;quot;Commence greeting in &amp;quot; + counter--);&lt;br /&gt;
        } else {&lt;br /&gt;
            plugin.getServer().broadcastMessage(&amp;quot;Welcome to Bukkit! Remember to read the documentation!&amp;quot;);&lt;br /&gt;
            this.cancel();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&amp;lt;/source&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 定时任务  ==&lt;br /&gt;
在完成定义工作后, 插件需要定时这个BukkitRunnable. BukkitRunnables 将被定时执行run()方法. BukkitRunnable 的方法列表能在这找到:[http://jd.bukkit.org/rb/apidocs/index.html?org/bukkit/scheduler/BukkitRunnable.html Javadocs for BukkitRunnable]. 所有的run方法都将返回[[#BukkitTask | BukkitTask]] 对象&lt;br /&gt;
&lt;br /&gt;
{{warning| Asynchronous tasks should never access any API in Bukkit}}&lt;br /&gt;
&lt;br /&gt;
=== 例子 ===&lt;br /&gt;
这是一个注册了PlayerJoinEvent监听器的插件, 定时任务将在玩家加入游戏后20tick执行. &lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;import org.bukkit.event.EventHandler;&lt;br /&gt;
import org.bukkit.event.Listener;&lt;br /&gt;
import org.bukkit.event.player.PlayerJoinEvent;&lt;br /&gt;
import org.bukkit.plugin.java.JavaPlugin;&lt;br /&gt;
import org.bukkit.scheduler.BukkitRunnable;&lt;br /&gt;
import org.bukkit.scheduler.BukkitTask;&lt;br /&gt;
&lt;br /&gt;
public final class ExamplePlugin extends JavaPlugin {&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onEnable() {&lt;br /&gt;
        new ExampleListener(this);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class ExampleListener implements Listener {&lt;br /&gt;
&lt;br /&gt;
    private final ExamplePlugin plugin;&lt;br /&gt;
&lt;br /&gt;
    public ExampleListener(ExamplePlugin plugin) {&lt;br /&gt;
        this.plugin = plugin;&lt;br /&gt;
        plugin.getServer().getPluginManager().registerEvents(this, plugin);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @EventHandler&lt;br /&gt;
    public void onJoin(PlayerJoinEvent event) {&lt;br /&gt;
        // 创建一个20tick后仅执行一次的任务&lt;br /&gt;
        BukkitTask task = new ExampleTask(this.plugin).runTaskLater(this.plugin, 20);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 自我取消例子 ===&lt;br /&gt;
这是采用之前提到的 ExampleSelfCancelingTask 定时为20tick延迟后执行 每10tick执行一次.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;import org.bukkit.event.EventHandler;&lt;br /&gt;
import org.bukkit.event.Listener;&lt;br /&gt;
import org.bukkit.event.player.PlayerJoinEvent;&lt;br /&gt;
import org.bukkit.plugin.java.JavaPlugin;&lt;br /&gt;
import org.bukkit.scheduler.BukkitRunnable;&lt;br /&gt;
import org.bukkit.scheduler.BukkitTask;&lt;br /&gt;
&lt;br /&gt;
public final class ExamplePlugin extends JavaPlugin {&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onEnable() {&lt;br /&gt;
        new ExampleListener(this);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class ExampleListener implements Listener {&lt;br /&gt;
&lt;br /&gt;
    private final ExamplePlugin plugin;&lt;br /&gt;
&lt;br /&gt;
    public ExampleListener(ExamplePlugin plugin) {&lt;br /&gt;
        this.plugin = plugin;&lt;br /&gt;
        plugin.getServer().getPluginManager().registerEvents(this, plugin);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    @EventHandler&lt;br /&gt;
    public void onJoin(PlayerJoinEvent event) {&lt;br /&gt;
        // 创建定时任务&lt;br /&gt;
        BukkitTask task = new ExampleSelfCancelingTask(this.plugin, 5).runTaskTimer(this.plugin, 10, 20);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Anonymous BukkitRunnable Example ===&lt;br /&gt;
An anonymous BukkitRunnable will allow you to schedule a task, without creating a new class with a name. This examples combines the above two basic examples.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;import org.bukkit.event.EventHandler;&lt;br /&gt;
import org.bukkit.event.Listener;&lt;br /&gt;
import org.bukkit.event.player.PlayerJoinEvent;&lt;br /&gt;
import org.bukkit.plugin.java.JavaPlugin;&lt;br /&gt;
import org.bukkit.scheduler.BukkitRunnable;&lt;br /&gt;
import org.bukkit.scheduler.BukkitTask;&lt;br /&gt;
&lt;br /&gt;
public final class ExamplePlugin extends JavaPlugin {&lt;br /&gt;
 &lt;br /&gt;
    @Override&lt;br /&gt;
    public void onEnable() {&lt;br /&gt;
        new ExampleListener(this);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
class ExampleListener implements Listener {&lt;br /&gt;
 &lt;br /&gt;
    private final ExamplePlugin plugin;&lt;br /&gt;
 &lt;br /&gt;
    public ExampleListener(ExamplePlugin plugin) {&lt;br /&gt;
        this.plugin = plugin;&lt;br /&gt;
        plugin.getServer().getPluginManager().registerEvents(this, plugin);&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    @EventHandler&lt;br /&gt;
    public void onJoin(PlayerJoinEvent event) {&lt;br /&gt;
        // 创建一个20tick执行的匿名任务&lt;br /&gt;
        new BukkitRunnable() {&lt;br /&gt;
        &lt;br /&gt;
            @Override&lt;br /&gt;
            public void run() {&lt;br /&gt;
                // What you want to schedule goes here&lt;br /&gt;
                plugin.getServer().broadcastMessage(&lt;br /&gt;
                    &amp;quot;Welcome to Bukkit! Remember to read the documentation!&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
        }.runTaskLater(this.plugin, 20);&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
}&amp;lt;/source&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= BukkitScheduler =&lt;br /&gt;
The [http://jd.bukkit.org/rb/apidocs/index.html?org/bukkit/scheduler/BukkitScheduler.html BukkitScheduler] allows plugins to schedule a [http://docs.oracle.com/javase/6/docs/api/index.html?java/lang/Runnable.html Runnable] and/or a [http://docs.oracle.com/javase/6/docs/api/index.html?java/util/concurrent/Callable.html Callable] , for execution at a later time. The list of methods for BukkitScheduler can be found in the [http://jd.bukkit.org/rb/apidocs/index.html?org/bukkit/scheduler/BukkitScheduler.html Javadocs for BukkitScheduler].&lt;br /&gt;
&lt;br /&gt;
{{Note|Plugins should not schedule a BukkitRunnable with the scheduler, instead they should run the BukkitRunnable with the desired schedule.}}&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
Example for directly scheduling an anonymous Runnable with the BukkitScheduler to run after 20 ticks.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import org.bukkit.Bukkit;&lt;br /&gt;
import org.bukkit.plugin.java.JavaPlugin;&lt;br /&gt;
import org.bukkit.scheduler.BukkitScheduler;&lt;br /&gt;
&lt;br /&gt;
public final class ExamplePlugin extends JavaPlugin {&lt;br /&gt;
    public void onEnable() {&lt;br /&gt;
        BukkitScheduler scheduler = Bukkit.getServer().getScheduler();&lt;br /&gt;
        scheduler.scheduleSyncDelayedTask(this, new Runnable() {&lt;br /&gt;
            @Override&lt;br /&gt;
            public void run() {&lt;br /&gt;
                // Do something&lt;br /&gt;
            }&lt;br /&gt;
        }, 20L);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Repeating Example===&lt;br /&gt;
Example for directly scheduling an anonymous Runnable with the BukkitScheduler to run every twenty ticks, forever, starting from when you schedule it.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import org.bukkit.Bukkit;&lt;br /&gt;
import org.bukkit.plugin.java.JavaPlugin;&lt;br /&gt;
import org.bukkit.scheduler.BukkitScheduler;&lt;br /&gt;
&lt;br /&gt;
public final class ExamplePlugin extends JavaPlugin {&lt;br /&gt;
    public void onEnable() {&lt;br /&gt;
        BukkitScheduler scheduler = Bukkit.getServer().getScheduler();&lt;br /&gt;
        scheduler.scheduleSyncRepeatingTask(this, new Runnable() {&lt;br /&gt;
            @Override&lt;br /&gt;
            public void run() {&lt;br /&gt;
                // Do something&lt;br /&gt;
            }&lt;br /&gt;
        }, 0L, 20L);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{warning| Asynchronous tasks should never access any API in Bukkit}}&lt;br /&gt;
&lt;br /&gt;
== BukkitTask ==&lt;br /&gt;
A [http://jd.bukkit.org/rb/apidocs/index.html?org/bukkit/scheduler/BukkitTask.html BukkitTask] object is returned whenever a Runnable is scheduled. This object represents the task the scheduled task being executed by the scheduler.  For more information see, [http://jd.bukkit.org/rb/apidocs/index.html?org/bukkit/scheduler/BukkitTask.html Javadocs for BukkitTask].&lt;br /&gt;
&lt;br /&gt;
== Callable and Future ==&lt;br /&gt;
A [http://docs.oracle.com/javase/6/docs/api/index.html?java/util/concurrent/Callable.html Callable] given to the scheduler to call synchronously returns a [http://docs.oracle.com/javase/6/docs/api/index.html?java/util/concurrent/Future.html Future]. These are standard Java classes, for more information see, [http://docs.oracle.com/javase/6/docs/api/index.html?java/util/concurrent/Callable.html Javadocs for Callable] and [http://docs.oracle.com/javase/6/docs/api/index.html?java/util/concurrent/Future.html Javadocs for Future]&lt;br /&gt;
&lt;br /&gt;
= Tips for thread safety =&lt;br /&gt;
The Bukkit API, with the exception of the scheduler package, is not thread safe nor guaranteed to be thread safe.&lt;br /&gt;
# Asynchronous tasks should never access any API in Bukkit.&lt;br /&gt;
# Do not access or modify shared collections from your asynchronous tasks. Normal collections are [http://stackoverflow.com/questions/1003026/hashmap-concurrency-issue not] [http://lightbody.net/blog/?p=307 thread-safe]. This also applies to objects which are not thread safe.&lt;br /&gt;
# An asynchronous task can schedule a synchronous task.&lt;br /&gt;
# A synchronous task can schedule an asynchronous task.&lt;br /&gt;
&lt;br /&gt;
{{Languages|Scheduler Programming}}&lt;/div&gt;</summary>
		<author><name>A390807154</name></author>
	</entry>
</feed>