我们有一个需要每两个小时运行一次的流程。这是一个需要在自己的线程上运行的进程,以免中断正常处理。
当它运行时,它将下载 10 万条记录并根据数据库对其进行验证。运行它的框架有很多管理这个过程的对象。这些对象只需要在进程运行时出现。
什么是更好的标准?
通过让它休眠直到我再次需要它来保持线程处于等待模式。或者,
完成后删除它并在下次需要时创建它?(系统定时器事件。)
我们有一个需要每两个小时运行一次的流程。这是一个需要在自己的线程上运行的进程,以免中断正常处理。
当它运行时,它将下载 10 万条记录并根据数据库对其进行验证。运行它的框架有很多管理这个过程的对象。这些对象只需要在进程运行时出现。
什么是更好的标准?
通过让它休眠直到我再次需要它来保持线程处于等待模式。或者,
完成后删除它并在下次需要时创建它?(系统定时器事件。)
两种解决方案之间没有太大区别。我倾向于更喜欢每次都创建线程的那个。
周围有一个线程会消耗资源(至少是内存)。在垃圾收集语言中,可能很容易将一些对象保留在该线程中,从而使用更多内存。如果您没有放置线程,则所有资源都将被释放并在两个小时内可供主进程使用。
当您想停止整个进程时,您的线程可能正在执行或未执行,您需要干净地中断线程。总是很难中断一个线程或者知道它是在睡觉还是在工作。你可能有一些比赛条件。按需启动线程可以让您摆脱那些潜在的问题:您知道是否启动了线程,在这种情况下调用thread_join
会让您等待线程完成。
由于这些原因,我会选择线程按需解决方案,即使另一个没有不可克服的问题。
每两个小时启动一个线程非常便宜,所以我会这样做。
但是,如果将来某个时间处理可能花费的时间超过运行间隔,您可能希望保持线程处于活动状态。这样,您将不会创建第二个线程来开始处理记录,而第一个线程仍在运行,可能会损坏数据或处理记录两次。
两者都应该没问题,但我倾向于在验证时间超过预期的情况下保留线程(例如:网络链接速度慢或数据库响应速度慢)。
当两个小时结束时,你怎么记得开始一个新线程?带计时器?(那是在另一个线程上!)另一个线程休眠到指定时间?关闭线程并根据在其他地方运行的东西重新启动它,如果其他东西在它自己的单独线程上,或者在两个小时结束时等待“创建”工作线程时阻塞主应用程序,那么你没有好处, 不?
让线程休眠...
我同意 Vilx 的观点,这主要是一个品味问题。两种方法都有处理和内存开销,但可能还不够重要。
如果您使用的是Java ,则可以检查Timer类。它允许您在给定的时间安排任务。
此外,如果您需要更多控制,您可以使用石英库。
我想实际上让线程进入睡眠状态是最有效的,结束它并重新创建它会“消耗”一些资源,而让它进入睡眠状态只会填充调度器中的一点空间,而如果需要,它的数据可以由操作系统分页.
但无论如何,这可能不是一个很大的差异,差异可能取决于操作系统的调度程序有多好,等等......
据我所知,这实际上取决于一件事……状态。
如果线程创建了很多在线程运行的下一次迭代期间有用的状态(分配内存),那么我会保留它。这样,如果某些事情自上次运行以来发生了变化,您的流程可以通过仅执行某些操作来优化其运行。
但是,如果进程创建的状态与要完成的工作量相比非常重要,并且您的机器上的资源不足,那么在两次执行之间保持状态可能不值得。如果是这样,那么您应该每次都从头开始重新创建线程。
我认为这只是品味问题。两者都很好。使用你觉得更容易实现的那个。:)
我将创建一次线程,并使用事件/条件变量让它休眠,直到有信号再次唤醒。这样,如果需要更改所需的时间量,您只需更改触发事件的时间,您的代码仍然很干净。
我认为这不是很重要,但最好的方法是非常依赖于平台的。
.NET System.Threading.Timer 在等待时不会产生任何费用,并且会在池线程上调用您的代码。从理论上讲,这将是您的两个建议中最好的。
如果您在像 Java 这样的垃圾收集系统上要考虑的另一件重要事情是,任何被睡眠线程强引用的东西都不是垃圾。在这方面,最好杀死空闲线程,并让它们以及它们引用的任何对象得到清理。
当然,这一切都取决于。但默认情况下,我会根据需要启动一个单独的进程(不是线程)。