我有一个小程序可以做以下事情:
主线程和线程t1周期性地请求某些内容,一个按钮将同时停止这两者。

public class HttpsConn {
    private static boolean stop = false;
    private static Timer t = null;

    public static void main(String[] arg)  {
        t = new Timer();
        A a = new A();
        t.schedule(a, 0, 1000);
        B b = new B();
        Thread t1 = new Thread(b);
        t1.start();
    }
    static class A extends TimerTask {
        @Override
        public void run() {
            if (stop)
                t.cancel();     //this.cancel();
            System.out.println("something to do");
        }
    }
    static class B extends A implements Runnable {
        @Override
        public void run() {
            System.out.println("simulate an operation from Swing Applet (click RESET button) to interrupt the thread.");
             stop = true;
        }
    }
}

我除了结果:
something to do
simulate an operation from Swing Applet (click RESET button) to interrupt the thread.

我得到的是:
something to do
simulate an operation from Swing Applet (click RESET button) to interrupt the thread.
something to do

我发现了一个类似的问题here,回答说在run()中取消了调用,但在这里似乎不起作用。
那么如何避免意外运行呢?
在带有注释的行上,t.cancel()this.cancel()有什么区别?它们导致相同的结果。
谢谢!

最佳答案

您的A计划以0的初始延迟和1的后续延迟运行。

第一个something to do是在0延迟后第一次执行。尚未设置stop标志,因此仅打印并退出。

一秒钟后,它由Timer再次调用。它检查stop标志,取消计时器(因为B已执行并设置了它),然后打印第二个something to do。它不应再次运行,因为现在已取消了计时器任务。

为了避免这种看似奇怪的行为,您可以使用类似以下内容的方法:

        if (!stop) {
            System.out.println("something to do");
        } else {
            t.cancel();     //this.cancel();
        }

请记住,cancel仅取消Timer,它不会终止Runnable的执行。

09-10 07:32
查看更多