【问题标题】:How To Stop Timer Thread to Change Variable Value如何停止计时器线程以更改变量值
【发布时间】:2021-03-15 20:50:48
【问题描述】:

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

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;
}

}

我将如何停止线程,以便在五秒后“布尔”变为真,并且我可以在我的其他类中返回新值?另一个类是 GUI,因此更改的值可以检查何时切换到另一个面板。

【问题讨论】:

    标签: java multithreading timer


    【解决方案1】:

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

    【讨论】:

    • 在这种特殊情况下,我认为 volatile 是首选解决方案,而不是替代解决方案。
    【解决方案2】:

    Answer by Serdar 是正确的。此外,您可以使用执行器服务来代替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 对象。可以向该未来对象询问在后台线程上执行的任务的结果。

    确保最终关闭执行器服务。否则后台线程池可能会像僵尸一样无限期地运行?‍♂️。

    你说:

    另一个类是 GUI

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-16
      • 1970-01-01
      • 2021-08-27
      • 1970-01-01
      • 2017-12-26
      • 2012-06-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多