gpt4 book ai didi

java - Grails 中的多线程 - 将域对象传递到每个线程会导致某些字段随机为空

转载 作者:行者123 更新时间:2023-12-02 13:41:57 25 4
gpt4 key购买 nike

我试图通过引入并行编程来加速 Grails 应用程序中的进程。这个特定的过程需要筛选数千个文档,从中收集必要的数据并将其导出到 Excel 文件。

经过几个小时的尝试追查此过程为何进行得如此缓慢后,我确定该过程必须做大量工作来从每个域对象收集数据的特定部分。 (示例:域对象内部有数据列表,此过程获取这些列表中的每个索引,并将其附加到带逗号的字符串中,以在 Excel 工作表的单元格中创建一个美观的排序列表。还有更多示例但这些应该不重要。)

因此,任何不是简单数据访问的内容(document.id、document.name 等)都会导致此过程花费很长时间。

我的想法是为每个文档使用线程来异步获取所有这些数据,当每个线程完成数据收集后,它可以返回主线程并放入excel表中,现在所有数据访问都非常简单,因为线程已经收集了所有数据。

这似乎有效,但是我在域对象和线程方面遇到了错误。每个线程都会传入其相应的文档域对象,但无论出于何种原因,文档域对象都会随机将其部分数据更改为 null。

例如:在将文档传递到线程之前,域对象的一部分将有一个如下所示的列表:[美国,英格兰,威尔士],随机在任何一点,该列表将如下所示线程:[美国,空,威尔士]。这种情况会在任何随机时间发生在域对象的任何随机部分。

生成线程:

def docThreadPool = Executors.newFixedThreadPool(1)
def docThreadsResults = new Future<Map>[filteredDocs.size()]
filteredDocs.each {
def final document = it
def future = docThreadPool.submit(new DocumentExportCallable(document))
docThreadsResults[docCount] = future
docCount++
}

从线程中获取数据:

filteredDocs.each {
def data = docThreadsResults[count].get()

build excel spreadsheet...
}

DocumentExportCallable 类:

class DocumentExportCallable implements Callable {
def final document

DocumentExportCallable(document) {
this.document = document
}

Map call() {
def data = [:]

code to get all the data...

return data
}
}

编辑:如下所示,如果我可以向您展示域对象,将会很有用。但是我无法做到这一点。但是,你们向我询问有关域对象的事实让我认为这可能就是问题所在。事实证明,域对象在线程中随机困惑的每个部分都是“映射”内域对象中的一个变量,它使用 SQL 连接来获取这些变量的数据。我刚刚了解到 Grails 中的惰性获取与急切获取。我想知道这是否可能是问题所在......默认情况下它被设置为延迟获取,因此每个线程对数据库的持续访问可能是出现问题的地方。我相信找到一种方法将其更改为急切获取可能会解决问题。

最佳答案

我知道为什么这些空值随机出现。现在一切似乎都正常,我的实现现在的执行速度比以前的实现快得多!

事实证明,即使在获取对象本身之后,当您访问这些字段时,具有 1-m 关系的 Grails 域对象也会进行单独的 sql 调用。这肯定导致这些线程进行非线程安全的 SQL 调用,从而创建了这些随机空值。在这种特定情况下将这些 1-m 属性设置为急切地获取可以解决该问题。

对于稍后阅读的任何人,您都需要阅读有关惰性获取与急切获取的内容,以便更好地理解。

至于代码:

这些是我的域对象中出现问题的 1-m 变量:

static hasMany = [propertyOne : OtherDomainObject, propertyTwo : OtherDomainObject, propertyThree : OtherDomainObject]

我在数据库调用中添加了一个标志,该标志将针对此特定情况启用此代码,因为我不希望始终在整个应用程序中急切地获取这些属性:

if (isEager) {
fetchMode 'propertyOne', FetchMode.JOIN
fetchMode 'propertyTwo', FetchMode.JOIN
fetchMode 'propertyThree', FetchMode.JOIN
setResultTransformer Criteria.DISTINCT_ROOT_ENTITY
}

我很抱歉,但目前我不记得为什么我必须将“setResultTransformer”放在上面的代码中,但如果没有它就会出现问题。也许稍后有人可以解释这一点,否则我相信谷歌搜索会解释。

关于java - Grails 中的多线程 - 将域对象传递到每个线程会导致某些字段随机为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42701650/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com