Groovy并发

Sve*_*ger 3 groovy multithreading

我对Groovy线程有疑问.

我的任务是以某种方式翻译给定目录中的每个文件,并将结果输出放在另一个目录中的文件中.

我编写了以下代码,它的工作原理如下:

static def translateDir(fromDir, targetDir) {
    def allFiles = new File(fromDir).listFiles()
    def numFiles = allFiles.length

    for (i in 0..(numFiles - 1))
        translate(allFiles[i].getAbsolutePath(), targetDir)
}
Run Code Online (Sandbox Code Playgroud)

现在,我尝试将此代码并行化,如下所示:

static def translateDir(fromDir, targetDir) {
    def allFiles = new File(fromDir).listFiles()
    def numFiles = allFiles.length
    def numCores = Runtime.getRuntime().availableProcessors()

    for (i in 0..(numCores - 1)) {
        println("Thread " + i + "starting")
        Thread.start {
            for (def j = i; j < numFiles; j += numCores) {
                println("j = " + j) 
                translate(allFiles[j].getAbsolutePath(), targetDir)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个不起作用并提供输出:

Thread 0 starting
Thread 1 starting
Thread 2 starting
Thread 3 starting
Run Code Online (Sandbox Code Playgroud)

nunCores是4,在我的测试用例中numFiles是3.这里发生了什么?

tim*_*tes 11

您正在启动线程,但随后您的程序在运行之前完成.

正如文档中所示,您需要调用join线程以等待它们完成

使用执行程序框架可能更容易,该框架在同一页面上进一步显示


编辑

只是为了好玩,我实现了一些使用Thread.start你正在努力实现的东西

// This will perform the task required for a list of files
def translate( List files ) {
  files.each {
    // We will just print it out, and sleep for a bit
    println it
    Thread.sleep( 300 )
  }
}

// makeWorker returns a closure that will process the files
def makeWorker( List files ) {
  { -> translate( files ) }
}

// Main processing function
void process( List files ) {
  int numCores = Runtime.getRuntime().availableProcessors()
  // Split the files to process into groups (one for each worker)
  def partitioned = (0..<numCores).collect { i ->
    files[ (i..<files.size()).step( numCores ) ]
  }
  // Then create a Thread for each group
  def threads = partitioned.collect { group ->
    Thread.start makeWorker( group )
  }
  // And wait for them all to finish
  threads*.join()
}

// Simulate the process with the letters a through z
process( 'a'..'z' )
Run Code Online (Sandbox Code Playgroud)


Gre*_*eek 8

好的,2件事:

  1. 在线程的隐式run()方法内部,您引用了'i'变量.我必须通过一个调试器来看看到底发生了什么,但从技术上讲,你甚至不应该访问'i',因为它不是最终的.所以,我建议创建一个Runnable对象,在构造函数中传递'i'.然后在线程上启动runnable.

  2. Groovy具有很好的并发支持 - 没有理由像你这样自己动手.看看GPars吧