当前位置: 首页 > 知识库问答 >
问题:

用于周期性数据库批插入的Java并发性

翁俊良
2023-03-14

场景:一个线程每秒被调用数千次,以对同一个表执行插入操作,目前正在逐个执行这些操作。

目标:定期批量插入以提高性能。

当线程的saveItem方法被调用时,尝试使用TimerTask将保存到列表中的对象添加到列表中,然后每2秒左右将它们组合起来进行批插入。

第一个想法是有两个列表,分别称为toSavetoSaveBackup。当调用线程的saveItem方法来保存某些内容时,它将被添加到toSave列表中,但一旦TimerTask启动并需要将所有内容保存到数据库中,它会将AtomicBoolean标志saveInProgress设置为true。该标志由saveItem检查,如果saveInProgress为真,它将添加到toSaveBackup而不是toSave。批量保存完成后,toSaveBackup中的所有项目都将移动到toSave列表中,列表上可能有一个同步块。

这是否一个合理的做法呢?还是有更好的最佳实践?我的谷歌搜索技能让我失望了,所以欢迎任何帮助。

杂项信息:

  • 所有这些插入到同一个表
  • 插入是由收到MQTT消息驱动的,所以在这一点之前我不能将它们组合成批处理

更新:对CKing下面的答案进行了调整,实现了预期的方法:每100毫秒运行一次Timer任务,并检查saveQueue的大小以及自批量保存以来已经过了多长时间。如果这些值中的任何一个超过了配置的限制(每2秒保存一次或每1000条记录保存一次等),那么我们保存。LinkedBlockingQueue用于简化同步化。

再次感谢大家的帮助!

共有1个答案

蒋栋
2023-03-14

看起来您的主要目标是等待预定义的时间量,然后触发插入。当插入正在进行时,您不希望其他插入请求等待插入完成。插入完成后,您希望对下一个插入请求再次重复相同的过程。

基于上述理解,我将提出以下解决方案。你不需要有两个单独的清单来实现你的目标。还请注意,为了便于解释,我提出了一个老式的解决方案。在我的解释结束时,我将介绍一些您可以使用的其他API。下面是:

  1. 定义每N秒运行一次的计时器计时器任务

您不再需要显式监视插入是否正在进行,或者在插入时创建ArrayList的副本。在这种情况下,您的ArrayList将成为共享资源。

如果您还希望size成为继续进行插入的决定因素,可以这样做:

  1. TimerCommission中定义一个名为waitAttemts的int。此字段表示如果listsize不够大,则Timer任务将不执行任何操作的连续唤醒次数。
  2. 每次TimerCommission唤醒时,它都可以执行类似于if(waitAttemps%3==0||list.size

注:内在锁定被用作解释该html" target="_blank">方法的一种手段。人们总是可以采用这种方法,并使用现代构造来实现它,例如阻塞队列,这样就不需要在阵列列表上手动进行同步。我还建议使用执行器。newSingleThreadScheduledExecutor()而不是TimerTask,因为它可以确保在任何给定时间只有一个线程运行,并且不会有线程重叠。此外,等待尝试的逻辑是指示性的,需要进行调整才能正常工作。

 类似资料:
  • 问题内容: 我需要找出一种将带有字段的记录插入数据库的方法,但我陷入了困境。 有谁知道我该怎么做?现在我有类似的东西。 但是,当我运行类似这样的命令时,出现错误:值的字符串表示形式的语法不正确。 这是sql语句的样子: 谢谢 问题答案: 当然,这将使你的代码更好,但是要回答你的问题,你需要告诉的字符串表示形式。在中(你不指定数据库供应商的名称),使用以下函数将字符串日期转换为:

  • 在我的本地设置中,我使用一个简单的H2数据库。“托管”解决方案将有另一个(类似但不相同)数据库。 我需要将最大可能的日期插入到DateTime列中。我试图用 但是,这会导致列中出现-169104626-12-11 20:08:15.9999999。 关于如何插入最长可能日期,是否有可靠的选项?

  • 参数: url - 返回JSON格式数据,数据格式与添加(更新)数据定义的data相同 liveLoadCallback - 当加载完成时执行的回调函数 duration - 周期性数据加载时间(以毫秒为单位) 周期性地从一个数据源加载数据,用法: var url = "dynamicallyAPI/data"; // 使用liveLoad() API加载URL中的数据。 // 设置回调。 //

  • 我正在尝试使用Java jdbc连接在mysql数据库中插入一行。。。。 这是我的密码, } 当我尝试运行代码时,我得到类强制转换异常。。。非常感谢您的帮助。这是我的学生。java类 } 当我运行代码时,我得到以下错误:线程“main”java中出现异常。lang.ClassCastException:类java。util。日期不能转换为java类。sql。jdbcsample中的日期(java.

  • 我创建了一个向MySql数据库插入数百万个值的程序。我读到过有关批插入的文章,它将优化我的程序并使其更快,但当我尝试这样做时,它以同样的方式工作。我没有将每个值插入数据库,而是每次将500个值保存在一个列表中,然后将它们插入一个大循环中,如下所示: 然后我删除列表中的所有值,并再次开始收集500个值。它不应该工作得更好吗? 我的插入代码是: 我有一些问题: 1。为什么当我批量插入时它不能更快地工作

  • 我试图在oracle数据库中插入一个日期,但我一直面临着一个转换问题。