如何使捕获外部进程线程安全的输出?
How to make capturing output from an external process thread-safe?
我写了一个小方法来执行 git
命令行工具并捕获它的输出:
def git(String command) {
command = "git ${command}"
def outputStream = new StringBuilder()
def errorStream = new StringBuilder()
def process = command.execute()
process.waitForProcessOutput(outputStream, errorStream)
return [process.exitValue(), outputStream, errorStream, command]
}
我将它与 GPars 一起使用以同时克隆多个存储库,例如
GParsPool.withPool(10) {
repos.eachParallel { cloneUrl, cloneDir->
(exit, out, err, cmd) = git("clone ${cloneUrl} ${cloneDir}")
if (exit != 0) {
println "Error: ${cmd} failed with '${errorStream}'."
}
}
}
但是,我相信我的 git
方法不是线程安全的:例如,第二个线程可以在第一个线程达到 [=16] 之前修改方法第一行中的 command
=]在方法的第五行。
我可以通过使整个 git
方法 synchronized
来解决这个问题,但这会破坏 运行 它在不同线程中的目的,因为我希望克隆并行发生。
所以我想像
那样做部分同步
def git(String command) {
def outputStream
def errorStream
def process
synchronized {
command = "git ${command}"
outputStream = new StringBuilder()
errorStream = new StringBuilder()
process = command.execute()
}
process.waitForProcessOutput(outputStream, errorStream)
return [process.exitValue(), outputStream, errorStream, command]
}
但我猜这也不安全,因为线程二 waitForProcessOutput()
可能比线程一早 return,搞砸了 outputStream
/ errorStream
变量。
获得此线程安全的正确方法是什么?
改变 eachParallel
闭包参数中的赋值语句如下:
def (exit, out, err, cmd) = git("clone ${cloneUrl} ${cloneDir}")
这将使变量成为闭包的局部变量,进而使它们成为线程安全的。 git()
方法没有问题。
我写了一个小方法来执行 git
命令行工具并捕获它的输出:
def git(String command) {
command = "git ${command}"
def outputStream = new StringBuilder()
def errorStream = new StringBuilder()
def process = command.execute()
process.waitForProcessOutput(outputStream, errorStream)
return [process.exitValue(), outputStream, errorStream, command]
}
我将它与 GPars 一起使用以同时克隆多个存储库,例如
GParsPool.withPool(10) {
repos.eachParallel { cloneUrl, cloneDir->
(exit, out, err, cmd) = git("clone ${cloneUrl} ${cloneDir}")
if (exit != 0) {
println "Error: ${cmd} failed with '${errorStream}'."
}
}
}
但是,我相信我的 git
方法不是线程安全的:例如,第二个线程可以在第一个线程达到 [=16] 之前修改方法第一行中的 command
=]在方法的第五行。
我可以通过使整个 git
方法 synchronized
来解决这个问题,但这会破坏 运行 它在不同线程中的目的,因为我希望克隆并行发生。
所以我想像
那样做部分同步def git(String command) {
def outputStream
def errorStream
def process
synchronized {
command = "git ${command}"
outputStream = new StringBuilder()
errorStream = new StringBuilder()
process = command.execute()
}
process.waitForProcessOutput(outputStream, errorStream)
return [process.exitValue(), outputStream, errorStream, command]
}
但我猜这也不安全,因为线程二 waitForProcessOutput()
可能比线程一早 return,搞砸了 outputStream
/ errorStream
变量。
获得此线程安全的正确方法是什么?
改变 eachParallel
闭包参数中的赋值语句如下:
def (exit, out, err, cmd) = git("clone ${cloneUrl} ${cloneDir}")
这将使变量成为闭包的局部变量,进而使它们成为线程安全的。 git()
方法没有问题。