【问题标题】:Using ExecutorService to execute 4 db2 fetch methods in parallel. Is this right way?使用 ExecutorService 并行执行 4 个 db2 fetch 方法。这是正确的方法吗?
【发布时间】:2022-10-25 02:10:42
【问题描述】:

所以我有 4 个从 DB2 获取数据的 java 方法,我已经评论了从 DB2 获取结果所需的相应时间:

db2.fetchCigarProducts(id) // time taken 625 ms
db2.fetchPowderProdcuts(id) // time taken 327 ms
db2.fetchLegacyCigars(id) // time taken 314 ms
db2.fetchDairyProduct(id) // time taken 443 ms

显然,所花费的时间会根据作为输入(参数)给出的 id 而有所不同,但这是大多数调用的平均时间。

这是代码的结构方式,调用 Function 的伪代码:

for(String itemId: combinedItemIds) {
   fetchAndProcessDataFromDB2(itemId);
}
public void fetchAndProcessDataFromDB2(itemId) {
    db2.fetchCigarProducts(id) // time taken 625 ms
    db2.fetchPowderProdcuts(id) // time taken 327 ms
    db2.fetchLegacyCigars(id) // time taken 314 ms
    db2.fetchDairyProduct(id) // time taken 443 ms
}

现在在上述正常流程中(没有任何多线程),每个 itemId 的 fetchAndProcessDataFromDB2 时间约为 1500 ms ~= 1.5 秒。

因此,为了并行处理这 4 种方法以节省时间,我将这 4 种方法同步,并尝试按以下方式使用 exectorService:

public void fetchAndProcessDataFromDB2(itemId) {
  ExecutorService executorService = Executors.newCachedThreadPool();

    executorService.execute(
                () -> { db2.fetchCigarProducts(id); }
    );
    executorService.execute(
                () -> { db2.fetchPowderProdcuts(id); }
    );
    executorService.execute(
                () -> { db2.fetchLegacyCigars(id); }
    );
    executorService.execute(
                () -> { db2.fetchDairyProduct(id); }
    );
   
    executorService.shutdown();
    executorService.awaitTermination(5, TimeUnit.SECONDS);
}

我预计上述方法中有 4 种将并行执行,并且预计总共需要 400-500 毫秒的粗略时间。 但令我惊讶的是,使用 executorService 的 fetchAndProcessDataFromDB2 所用的总时间约为 1.7 秒,比没有多线程的 fetchAndProcessDataFromDB2 方法多一点。

有人可以帮我理解为什么会这样吗?任何提示/指针表示赞赏。

【问题讨论】:

  • 启动执行器服务可能需要一些时间来初始化。为什么不重复使用现有的?
  • 运行 4 个同时访问相同底层资源的操作并不能保证加快速度 - 您可能只是导致该资源在处理这些请求时进行额外的上下文切换。此外,请检查您没有得到所有 4 个请求共享的任何对象(例如使用一个 JDBC 连接而不是每个线程一个)或任何与共享对象同步的对象。

标签: java multithreading db2 executorservice threadpoolexecutor


【解决方案1】:

有人可以帮我理解为什么会这样吗?任何提示/指针表示赞赏。谢谢

您的代码看起来是正确的,所以我怀疑 db2 对象中的某些东西正在序列化数据库操作,或者服务器可能无法更快地同时执行 4 个查询。

更具体地说,db2 对象可能有一个用于与数据库通信的数据库连接。它可能会在 fetch 调用中锁定连接,因此即使有多个线程调用 fetch...(),但实际上只有 1 个线程在一次工作。

就数据库而言,每个fetch... 操作都可能导致对大表进行某种形式的表扫描。同时运行多个它们不一定会导致提取运行得更快,甚至可能导致底层存储机制运行得更慢,因为它必须在并发操作期间从 4 个不同的位置读取。

【讨论】:

  • 谢谢@Gray,不知道我是怎么错过的。你是对的,我通过使用我的数据库对象的 4 个不同的静态实例解决了这个问题,它就像一个魅力!
猜你喜欢
  • 2015-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-11
  • 2018-12-31
  • 2021-04-29
相关资源
最近更新 更多