【问题标题】:infinite loop database check无限循环数据库检查
【发布时间】:2013-05-14 05:39:46
【问题描述】:

我正在使用 JDBC,需要不断检查数据库是否有变化的值。

我目前有一个无限循环运行,内部循环迭代一个变化的值,每次迭代都检查数据库。

public void runInBG() { //this method called from another thread
    while(true) {
     while(els.hasElements()) {
      Test el = (Test)els.next();
       String sql = "SELECT * FROM Test WHERE id = '" + el.getId() + "'";
       Record r = db.getTestRecord(sql);//this function makes connection, executeQuery etc...and return Record object with values
       if(r != null) {
         //do something
       }
     }
    }
}

我认为这不是最好的方法。

我想的另一种方式是相反的,继续迭代数据库。

更新

感谢您提供有关计时器的反馈,但我认为它不会解决我的问题。 一旦数据库发生变化,我需要根据变化的值(示例代码中的“els”)几乎立即处理结果。

即使数据库没有变化,它仍然需要不断检查变化的值。

更新 2

好的,对于任何对答案感兴趣的人,我相信我现在有了解决方案。基本上解决方案不是为此使用数据库。加载、更新、添加等……只需要从数据库到内存。 这样您就不必经常打开和关闭数据库,您只需在对数据库进行更改时处理数据库,并将这些更改反映到内存中,并且只处理当时内存中的任何内容。 当然,这会占用更多内存,但性能是这里的绝对关键。

至于定期的“计时器”答案,很抱歉,但这根本不对。没有人回答为什么使用计时器可以解决这种特殊情况。

但再次感谢您的反馈,它仍然很有帮助。

【问题讨论】:

  • (+1) 好问题...我能看到这样做的唯一方法是在数据库端添加某种触发器。我也不喜欢这样,因为它不受程序的控制,可能过于具体。
  • 您的应用程序控制是否也更新和插入?
  • 是的,Peeyush。我编写了类来处理所有数据库交互。
  • 嗨 Jaco,请查看更新的解决方案。
  • 您应该发布 update2 作为答案并接受它!

标签: java sql jdbc h2


【解决方案1】:

另一种可能性是使用ScheduledThreadPoolExecutor

您可以实现一个包含您的逻辑的Runnable,并将其注册到ScheduledExecutorService,如下所示:

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
executor.scheduleAtFixedRate(myRunnable, 0, 5, TimeUnit.SECONDS);

上面的代码创建了一个ScheduledThreadPoolExecutor,它的池中有10个线程,并注册了一个Runnable,它将在5秒内立即开始运行。


要安排您的可运行文件,您可以使用:

scheduleAtFixedRate

创建并执行一个周期性动作,该动作在给定的初始延迟后首先启用,然后在给定的周期内启用;也就是说,执行将在 initialDelay 之后开始,然后是 initialDelay+period,然后是 initialDelay + 2 * period,依此类推。

scheduleWithFixedDelay

创建并执行一个周期性操作,该操作首先在给定的初始延迟之后启用,随后在一个执行的终止和下一个执行的开始之间具有给定的延迟。


here你可以看到ThreadPoolExecutor的优点,看看它是否符合你的要求。我建议这个问题:Java Timer vs ExecutorService? 也是为了做出正确的决定。

【讨论】:

    【解决方案2】:

    while(true) 保留在runInBG() 中是个坏主意。你最好去掉那个。相反,您可以使用 Scheduler/Timer(使用 TimerTimerTask)定期调用 runInBG() 并检查数据库中的更新。

    【讨论】:

    • 你可以跳过TimerTimerTask 的编码,方法是使用像quartz这样处理计划操作的框架
    • 同意使用调度程序进行调度是可行的方法,但是由于 OP 没有提及使用第三方库的任何内容,因此使用标准 java 类似乎是一个不错的选择!如果 OP 可以使用 3p 库,则可以稍后实施调度!
    • 仅供参考,我自己是 Quartz 用户! :)
    • 仅仅添加信息以防手动配置Timer 会让人头疼,因为像这样的框架已经处理了很多问题。是的,我是石英用户(免责声明:我与图书馆开发无关,也与任何客户支持无关,只是一个快乐的用户)。
    • 这必须不断检查,因为当数据库中发生任何更改时,必须处理结果。我不明白如何使用计时器来解决这个问题。
    【解决方案3】:

    你可以使用计时器--->

    Timer timer = new Timer("runInBG");
    
        //Taking an instance of class contains your repeated method.
        MyClass t = new MyClass();
    
        timer.schedule(t, 0, 2000);
    

    【讨论】:

      【解决方案4】:

      正如您在上面的评论中所说,如果应用程序控制更新和插入,那么您可以创建一个框架来通知“BG”线程或进程有关数据库中的更改。通知可以通过网络通过 JMS 或使用观察者模式的内部 VM 或本地和远程通知。

      你可以有通用的通知消息(它可以是本地通知的类或远程通知的文本消息)

      <Notification> 
        <Type>update/insert</Type>
        <Entity>
           <Name>Account/Customer</Name>
           <Id>id</Id>
        <Entity> 
      </Notification>
      

      【讨论】:

        【解决方案5】:

        为了避免“忙循环”,我会尝试使用触发器。 H2 还支持DatabaseEventListener API,这样您就不必为每个表创建触发器。

        这可能并不总是有效,例如,如果您使用远程连接。

        【讨论】:

          【解决方案6】:

          更新 2

          好的,对于任何对答案感兴趣的人,我相信我现在有了解决方案。基本上解决方案不是为此使用数据库。加载、更新、添加等……只需要从数据库到内存。这样您就不必经常打开和关闭数据库,您只需在对数据库进行更改时处理数据库,并将这些更改反映到内存中,并且只处理当时内存中的任何内容。当然,这会占用更多内存,但性能是绝对关键。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-12-18
            • 2021-05-19
            • 1970-01-01
            • 2014-04-12
            • 2014-02-27
            • 2020-11-07
            相关资源
            最近更新 更多