Java TimerTask, не останавливается при вызове отмены

So...

Я создаю плагин.

У меня есть основной класс под названием Basics

Глобально в Basics я создаю:

static Timer enterdungeon = new Timer();
static Timer finddungeon = new Timer();
static Timer lootdungeon = new Timer();

Также у меня есть класс с именем задача

Таймер входа в подземелье представляет собой фиксированный период времени и, кажется, работает, как и ожидалось, при использовании. То же самое и с таймером lootdungeon.

Таймер finddungeon может быть прерван, если срабатывает основное событие.

Событие ДЕЙСТВИТЕЛЬНО вызывает штраф, верхняя строка в этом событии: finddungeon.cancel();

после запуска таймера lootdungeon.

проблема в том, что таймер finddungeon не отменяется, он продолжает работать, ниже приведен класс задачи:

import java.util.TimerTask;
import me.boduzapho.Basics.DoWarp.Returner;
import org.bukkit.entity.Player;

public class task extends TimerTask
{
private final Player _player;
private final int ticks;
private int cnt = 0;
private final int _sec;
private final String _message;

public task(Player player, int sec, String message)
{
    this._player = player;
    this._sec = sec;
    this._message = message;
    this.ticks = sec;
}

private void timetoloot(Player p)
{

    p.sendMessage("SUCCESS! Nice Job, Enjoy the loot!");
    Returner loc1 = DoWarp.getwarp("launch", Basics.warps, Basics.wx,Basics.wy, Basics.wz, p);
    DoWarp.warpme(loc1.x, loc1.y, loc1.z, p, false, Basics.plugin);

}

private void failedwhiteblock(Player p)
{
    p.sendMessage("FAIL! You did not find the white block. Sending you back. TRY AGAIN!");
    Returner loc1 = DoWarp.getwarp("launch", Basics.warps, Basics.wx, Basics.wy, Basics.wz, p);
    DoWarp.warpme(loc1.x, loc1.y, loc1.z, p, false, Basics.plugin);

}

private void enterdungeon(Player p)
{
    Basics.Stage.setLine(3, "Off you Go!");
    Basics.Stage.update();
    Basics.Stage.setLine(0, "");
    Basics.Stage.setLine(1, "");
    Basics.Stage.setLine(2, "");
    Basics.Stage.setLine(3, "");
    Basics.Stage.update();

    Basics.cDoClear(p);
    Basics.cDoSpawners(p);
    Basics.cDoRed(p);
    Returner loc1 = DoWarp.getwarp("dstart", Basics.warps, Basics.wx, Basics.wy, Basics.wz, p);
    DoWarp.warpme(loc1.x, loc1.y, loc1.z, p, false, Basics.plugin);
    Basics.DungeonPlayer = p;
    p.sendMessage("Welcome to the Dungeon, you have 1 minuite to locate and click the white block.");
    p.sendMessage("If you fail you will be returned to spawn. If you find it the treasures will be revieled");
    p.sendMessage("and the monsters banished for 1 min so you can loot the chests! After which you will");
    p.sendMessage("Be warped back to spawn with your Loot!");
    Basics.finddungeon.schedule(new task(_player, 30, "Time left to find the WHITE block :"), 0, 1000);
    Basics.enterdungeon.cancel();
}

@Override
public void run()
{
    while (cnt < ticks)
    {
        try
        {
            Thread.sleep(1 * 1000);
            _player.sendMessage(_message + " " + Integer.toString(_sec - cnt));
            ++cnt;
        }
        catch (InterruptedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    _player.sendMessage("Done!");
    if (_message == "Time left:")
    {
        enterdungeon(_player);
    }

    if (_message == "Time left to find the WHITE block :")
    {
        failedwhiteblock(_player);
    }

    if (_message == "Time left to LOOT:")
    {
        timetoloot(_player);
    }

    //

    return;

}
}

Вот функция, вызываемая в Основах (основной класс), которая должна отменить таймер finddungeon.

// white block in dungeon
        if (DungeonPlayer == player)
        {
            if ((block != null) && (block.getType() == Material.WOOL))
            {
                player.sendMessage("Canceling finddungeon from Basics");
                finddungeon.cancel();
                cDoClear(player);
                cDoChests(player);

                player.sendMessage("Congradulations! Time to Loot your rewards for finding the White Block!");
                Timer lootdungeon = new Timer();
                lootdungeon.schedule(new task(player, 10, "Time left to LOOT:"), 0, 1000);

                return;
                // ***
            }
        }

Кто-нибудь может пролить свет на это?


person MarkKiessling    schedule 29.02.2012    source источник
comment
Я попытался глобально объявить логическую переменную, которая проверяется внутри события запуска таймера. По умолчанию я установил для этого значение false, и это указывает время для продолжения. Когда запускается событие белого блока, я устанавливаю для него значение true, чтобы указать событию запуска на отмену вызова (в соответствии с инструкциями из java, как надежный способ убить таймер). Это также не работает. Через отраженный чат я вижу, что логическая переменная таймера меняется с ложной на истинную, а функция cancel(); вызывается, но таймер просто продолжает идти.   -  person MarkKiessling    schedule 29.02.2012


Ответы (1)


Причина TimerTask.cancel ничего не делает с активной задачей, он просто очищает планировщик. Вам придется переопределить метод отмены или просто использовать его в качестве отправной точки:

class MyTimerTask extends TimerTask {
    private volatile Thread thread;

    @Override
    public void run() {
        thread = Thread.currentThread();
        //do your task and keep your eye on InterruptedException when doing Sleeps, Waits
        //also check Thread.interrupted()
    }

    public boolean cancel() {
        Thread thread = this.thread;
        if (thread != null) {
            thread.interrupt();
        }
        return super.cancel();
    }
}
person Tosha    schedule 21.05.2013