如何停止定时器线程改变变量值

How To Stop Timer Thread to Change Variable Value

我有一个持续运行的计时器 class。当它达到五秒时,我想更改一个将被另一个 class 使用的布尔值。但是,由于它有自己的线程,变量的值没有改变,我无法检索更改的布尔值。

public class Time extends TimerTask {
Timer s = new Timer();
boolean bool;
int secondsPassed = 0;
Toolkit toolkit = Toolkit.getDefaultToolkit();

public Time() {
    bool = false;
}
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        secondsPassed++;
        if(secondsPassed == 5) {
            System.out.println("Seconds passed: " + secondsPassed);
            toolkit.beep();
            bool = true;
        }
    }
};

public void nextPanel() {
    toolkit = Toolkit.getDefaultToolkit();
    s.scheduleAtFixedRate(task, 1000, 1000);
}

public boolean throwbool() {
    return bool;
}

}

我如何停止线程以便在五秒后“bool”变为真并且我可以 return 我的另一个 class 中的新值?另一个 class 是一个 GUI,因此更改的值作为检查何时切换到另一个面板的检查。

如果变量 bool 被多个线程访问,则存在数据竞争。除非使用显式同步来控制对 bool 的访问,否则对 bool 所做的修改可能对其他线程不可见。您可以将 bool 声明为 volatile 以实现此目的,并且对 bool 的所有更改都应立即对其他线程可见。

是正确的。此外,您可以使用执行程序服务而不是 TimerTask.

TimerTimerTask 类 通常由执行程序服务框架取代,如 Javadoc 中所述。

对于定时任务,使用ScheduledExecutorService

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;

定义一个具有 run 方法的 Runnable 对象。您可以使用 lambda 语法或常规语法。

Runnable r = () -> {   // lambda syntax
    … work to be done on background thread …
};

将您的任务安排到 运行 五秒后一次。

ses.schedule( r , 5 , TimeUnit.SECONDS ) ;

你说你的任务应该设置一个布尔值来跨线程通信。您需要访问该布尔线程安全。我的首选方法是使用 AtomicBoolean 对象将布尔值包装在线程安全的访问器方法中。不需要 volatilesynchronized.

AtomicBoolean flag = new AtomicBoolean() ;

您的任务可以设置该布尔值。

Runnable r = () -> {   // lambda syntax
    flag.set( true ) ;  // Automatically thread-safe because of `AtomicBoolean`. 
};

如果您更喜欢生成值,请捕获 .schedule 方法返回的 ScheduledFuture 对象。可以向该 future 对象询问在后台线程上执行的任务的结果。

确保最终关闭执行程序服务。否则后台线程池可能运行无限期像个僵尸‍♂️。

你说:

The other class is a GUI

什么 GUI 工具包?如果是 Swing、JavaFX 或 Vaadin,切勿从后台线程访问 GUI 中的任何小部件。使用 GUI 框架提供的任何适当机制来请求 GUI 运行 在其自己的线程上使用一些代码来更新其小部件。