如何停止定时器线程改变变量值
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
.
Timer
和 TimerTask
类 通常由执行程序服务框架取代,如 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
对象将布尔值包装在线程安全的访问器方法中。不需要 volatile
或 synchronized
.
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 运行 在其自己的线程上使用一些代码来更新其小部件。
我有一个持续运行的计时器 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
.
Timer
和 TimerTask
类 通常由执行程序服务框架取代,如 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
对象将布尔值包装在线程安全的访问器方法中。不需要 volatile
或 synchronized
.
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 运行 在其自己的线程上使用一些代码来更新其小部件。