服务端错误 2026-02-02 23:07 采纳率: 80%
浏览 7
已结题

关于#Java#的问题,如何解决?(相关搜索:定时器|数据库|时间戳)

Java实现记录试验的运行时间,有开始暂停结束功能,需要计时。
(典型的计时器/定时器管理问题,更具体地说是任务耗时统计或会话时长统计问题)
思路:
(在数据库中存储两个字段,一个是开始运行的时间realtime,一个是当前时间与上一次开始运行时间realtime的差值longtime。当暂停时,将当前时间与realtime的差值时间戳记录为longtime,重新运行时更新realtime为当前时间。前端每次获取当前时间与realtime的差值加上longtime得到总时长,如果暂停则只获取longtime。)

开始:记录开始时间(realtime)到数据库,并将longtime设为0(如果是从头开始的话)。

暂停:计算当前时间与realtime的差值,然后加到longtime上,并更新longtime字段。同时,将realtime设为null或者不更新(因为暂停后,realtime不再有意义,直到再次开始)。

继续:更新realtime为当前时间,longtime保持不变。

结束:计算总运行时间(当前时间与realtime的差值加上longtime),并更新到数据库,同时可以清空realtime和longtime(或者标记为结束)。

但是,注意:我们可能需要考虑多次暂停和继续的情况。

另一种设计:我们可以在每次暂停时,将当前时间段(从上次开始到本次暂停)的差值累加到longtime,然后重新开始的时候更新realtime为当前时间。
这样,总运行时间 = longtime + (如果当前正在运行,则加上当前时间与realtime的差值,否则不加)。

因此,我们需要在数据库中存储两个字段:
realtime: 最近一次开始运行的时间(如果当前处于运行状态,则不为空;如果处于暂停状态,则为空)
longtime: 累计运行时间(每次暂停时累加)

但是,为了处理方便,我们可以将realtime设置为可以为空,当realtime为空时,表示当前处于暂停状态。

步骤:

开始:
如果realtime为空,则设置realtime为当前时间,longtime不变(如果是第一次开始,则longtime为0)。
如果realtime不为空,说明已经在运行,则不做任何操作(或者可以重新开始,即重置realtime和longtime)。

暂停:
如果realtime不为空,则计算当前时间与realtime的差值,将差值累加到longtime,然后将realtime设为空。

继续:
如果realtime为空,则设置realtime为当前时间。

结束:
计算总运行时间:如果realtime不为空,则总时间 = longtime + (当前时间 - realtime),否则总时间 = longtime。
然后可以将realtime和longtime重置(或者记录到另一个字段中,然后清空这两个字段)。

但是,我们还需要考虑前端显示的问题。前端需要实时显示当前已经运行的时间(如果正在运行,则包括当前段的时间)。

前端获取总运行时间的逻辑:
如果realtime不为空(即正在运行),则总时间 = longtime + (当前时间 - realtime)
否则,总时间 = longtime


另一种常见的方法是存储每一次运行的时间段(开始时间和结束时间),然后通过累加这些时间段来计算总时长。
这种方法更符合事件溯源的思想,可以记录完整的操作历史,并且可以应对更复杂的需求(比如多次暂停、继续,甚至需要记录每次运行的详细信息)。

设计思路:

创建一张表,记录每次运行的开始时间和结束时间(如果还未结束,则结束时间为NULL)。

当用户开始实验时,插入一条记录,记录开始时间,结束时间为NULL。

当用户暂停实验时,将最近一条结束时间为NULL的记录更新结束时间为当前时间。

当用户继续实验时,再插入一条新的开始时间记录,结束时间为NULL。

当用户结束实验时,同样更新最近一条结束时间为NULL的记录为当前时间。

总时长可以通过累加所有记录的结束时间与开始时间之差得到。

这种方法的优点:

记录了每一次运行的精确时间段,可以回溯历史。

不需要维护状态字段,通过开始和结束时间就可以判断当前是否在运行(最近一条记录结束时间为NULL表示正在运行)。

可以处理多次暂停/继续的情况。

缺点:

如果实验运行次数很多,会产生很多记录,累计计算总时长可能需要遍历所有记录(但可以通过缓存总时长来优化)。

在频繁暂停/继续的场景下,记录数会很多。

  • 写回答

2条回答 默认 最新

  • 关注

    方案1:只想要总时长(简单不折腾)

    • 数据库就俩字段:realtime(最近开始时间,null=暂停)、longtime(累计毫秒数)
    • 操作逻辑:
      1. 开始:realtime设当前时间,首次开始则longtime置0
      2. 暂停:算「当前时间 - realtime」,累加到longtime,再把realtime设null
      3. 继续:realtime更改为当前时间,longtime不动
      4. 结束:总时长=(realtime不为null就加「当前时间 - realtime」)+ longtime
    • 前端:拿俩字段后,运行中就本地算实时时长,暂停直接显longtime

    方案2:要追溯每次启停记录(留痕用)

    • 数据库表:experiment_id(关联实验)、start_time(开始时间)、end_time(结束时间,null=运行中)
    • 操作逻辑:
      1. 开始/继续:插一条记录,start_time=当前时间,end_time=null
      2. 暂停/结束:更最近一条end_time为null的记录,设为当前时间
      3. 总时长:累加所有记录的「end_time - start_time」(未结束的用当前时间减)
    • 优点:能查历史启停,缺点:频繁操作会多存几条记录

    关键注意点

    1. 时间统一用System.currentTimeMillis(),避免乱码
    2. 同一实验操作加行锁(比如MySQL的for update),防止并发错
    3. 前端不用每秒调接口,本地计时+10秒同步一次就行
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 3月10日
  • 已采纳回答 3月2日
  • 修改了问题 2月2日
  • 修改了问题 2月2日
  • 展开全部