为什么不在当前线程中实现一个时间控制的任务呢?
Why not implement a time controlled task in the current thread?
当实现在特定时间范围内处理任务的功能时(例如,每 1 分钟监视一个值,总共 10 分钟的时间限制),流行的解决方案是使用 Timer
或ScheduledExecutorService
java util 类 在单独的线程上安排任务。
想知道为什么不直接在当前线程上实现定时任务,而是创建一个新线程来处理它?
您不能在当前线程中执行此操作,因为您的主程序 运行 在它自己的线程中,您无法对其进行太多控制。你最多可以让它进入睡眠状态。因此,您将在一个线程上启动您的主程序,该线程将分拆另一个线程以 运行 按计划执行您的任务。
休眠主线程会冻结您的应用程序
multi-threading 的全部要点是从 运行 应用程序的初始线程卸载工作。
一个线程休眠到某个时间没有做任何其他工作。如果您的应用程序的主线程处于休眠状态,那么您的应用程序将完全挂起且无用。如果线程 运行使您的 GUI 处于休眠状态,那么您的应用程序对用户来说似乎是冻结的,显然是崩溃的,并且实际上毫无用处。
另外,作为, threads as currently implemented in Java are relatively expensive in terms of memory and CPU. So we generally avoid having more than a few/several/dozens of threads running at a time. In the future, if Project Loom succeeds with its virtual threads,这种情况可能会发生根本性的改变。
您发表评论:
I think maybe I can do start time stop->monitor-> return-> sleep current thread-> monitor, quit monitor when condition met or time out?
这实际上就是 ScheduledExecutorService 所做的。您将任务定义为 Runnable
或 Callable
。执行程序服务 运行 定期执行您的任务。在该任务中,您可以检查您正在等待的条件。
所以你不需要重新发明轮子。使用内置于 Java 中的 Executors 框架;太棒了
搜索那个 class 名字。关于这个主题已经写了很多,其中一些是我撰写的。搜索以了解更多信息。
关于 Timer
,class 多年前已被 Executors 框架取代。 Java文档中记录了这一事实。
任务自行重新安排
您阐明了您的目标是每分钟检查一次条件,最多十次。
执行此操作的一种方法是让任务自行重新安排。
public class ConditionCheckingTask implements Runnable
{
private final ScheduledExecutorService ses ;
private final Instant whenInstantiated = Instant.now() ;
// Constructor
public ConditionCheckingTask( final ScheduledExecutorService ses ) {
this.ses = ses ;
}
@Override
public void run() {
if( someConditionIsTrue ) {
doSomething ;
} else if ( ChronoUnit.MINUTES.between( this.whenInstantiated , Instant.now() ) > 10 ) {
// We have exceeded our time limit, so let this task die.
return ;
} else { // Else wait a minute to check condition again.
this.ses.schedule( this , 1 , TimeUnit.MINUTES ) ;
}
}
}
确保访问 someConditionIsTrue
是 thread-safe。例如,如果某个其他线程正在翻转一个布尔标志来指示我们的任务,则将该标志设置为 AtomicBoolean
。要了解更多信息,请搜索 Stack Overflow 并阅读下面列出的书籍。
在您的应用中的某处,实例化并记住一个 ScheduledExecutorService
对象。
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() ;
确保在您的应用程序退出之前最终关闭执行程序服务。搜索以了解更多信息。这已在 Stack Overflow 上多次解决。
实例化你的任务。将计划的执行程序服务传递给任务的构造函数,以便它可以每分钟重新安排一次。
ConditionCheckingTask task = new ConditionCheckingTask( scheduledExecutorService ) ;
要开始工作,请安排 运行 该任务,几乎没有延迟。
scheduledExecutorService.schedule( task , 0 , TimeUnit.MINUTES ) ;
作为第一个 运行 的一部分,任务将自行重新安排。
注意:在部署任何 multi-threaded 代码之前,请务必仔细阅读 Goetz 等人的优秀书籍,Java Concurrency In Practice。
Wondering why not just implement the timed task on the current thread
instead of creating a new thread to handle that?
您的“当前”线程可能是正在处理主要请求的线程(例如,http 请求或 task/job 协调器)。其中之一的定时任务会将此线程与任何其他工作联系起来,直到任务完成。在基于 http 的服务上,这可能会导致 http 超时等,这对于最终用户体验和计算资源使用来说都不是一个好的设计。
通常,作为一种好的做法,您不会为该任务生成另一个新线程,而是使用线程池来有效利用资源。
当实现在特定时间范围内处理任务的功能时(例如,每 1 分钟监视一个值,总共 10 分钟的时间限制),流行的解决方案是使用 Timer
或ScheduledExecutorService
java util 类 在单独的线程上安排任务。
想知道为什么不直接在当前线程上实现定时任务,而是创建一个新线程来处理它?
您不能在当前线程中执行此操作,因为您的主程序 运行 在它自己的线程中,您无法对其进行太多控制。你最多可以让它进入睡眠状态。因此,您将在一个线程上启动您的主程序,该线程将分拆另一个线程以 运行 按计划执行您的任务。
休眠主线程会冻结您的应用程序
multi-threading 的全部要点是从 运行 应用程序的初始线程卸载工作。
一个线程休眠到某个时间没有做任何其他工作。如果您的应用程序的主线程处于休眠状态,那么您的应用程序将完全挂起且无用。如果线程 运行使您的 GUI 处于休眠状态,那么您的应用程序对用户来说似乎是冻结的,显然是崩溃的,并且实际上毫无用处。
另外,作为
您发表评论:
I think maybe I can do start time stop->monitor-> return-> sleep current thread-> monitor, quit monitor when condition met or time out?
这实际上就是 ScheduledExecutorService 所做的。您将任务定义为 Runnable
或 Callable
。执行程序服务 运行 定期执行您的任务。在该任务中,您可以检查您正在等待的条件。
所以你不需要重新发明轮子。使用内置于 Java 中的 Executors 框架;太棒了
搜索那个 class 名字。关于这个主题已经写了很多,其中一些是我撰写的。搜索以了解更多信息。
关于 Timer
,class 多年前已被 Executors 框架取代。 Java文档中记录了这一事实。
任务自行重新安排
您阐明了您的目标是每分钟检查一次条件,最多十次。
执行此操作的一种方法是让任务自行重新安排。
public class ConditionCheckingTask implements Runnable
{
private final ScheduledExecutorService ses ;
private final Instant whenInstantiated = Instant.now() ;
// Constructor
public ConditionCheckingTask( final ScheduledExecutorService ses ) {
this.ses = ses ;
}
@Override
public void run() {
if( someConditionIsTrue ) {
doSomething ;
} else if ( ChronoUnit.MINUTES.between( this.whenInstantiated , Instant.now() ) > 10 ) {
// We have exceeded our time limit, so let this task die.
return ;
} else { // Else wait a minute to check condition again.
this.ses.schedule( this , 1 , TimeUnit.MINUTES ) ;
}
}
}
确保访问 someConditionIsTrue
是 thread-safe。例如,如果某个其他线程正在翻转一个布尔标志来指示我们的任务,则将该标志设置为 AtomicBoolean
。要了解更多信息,请搜索 Stack Overflow 并阅读下面列出的书籍。
在您的应用中的某处,实例化并记住一个 ScheduledExecutorService
对象。
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() ;
确保在您的应用程序退出之前最终关闭执行程序服务。搜索以了解更多信息。这已在 Stack Overflow 上多次解决。
实例化你的任务。将计划的执行程序服务传递给任务的构造函数,以便它可以每分钟重新安排一次。
ConditionCheckingTask task = new ConditionCheckingTask( scheduledExecutorService ) ;
要开始工作,请安排 运行 该任务,几乎没有延迟。
scheduledExecutorService.schedule( task , 0 , TimeUnit.MINUTES ) ;
作为第一个 运行 的一部分,任务将自行重新安排。
注意:在部署任何 multi-threaded 代码之前,请务必仔细阅读 Goetz 等人的优秀书籍,Java Concurrency In Practice。
Wondering why not just implement the timed task on the current thread instead of creating a new thread to handle that?
您的“当前”线程可能是正在处理主要请求的线程(例如,http 请求或 task/job 协调器)。其中之一的定时任务会将此线程与任何其他工作联系起来,直到任务完成。在基于 http 的服务上,这可能会导致 http 超时等,这对于最终用户体验和计算资源使用来说都不是一个好的设计。 通常,作为一种好的做法,您不会为该任务生成另一个新线程,而是使用线程池来有效利用资源。