Multithreading Groovy并发

Multithreading Groovy并发,multithreading,groovy,Multithreading,Groovy,我对Groovy线程有一个问题 我的任务是以某种方式翻译给定目录中的每个文件 并将结果输出放在另一个目录中的文件中 我编写了以下代码,可以正常工作: static def translateDir(fromDir, targetDir) { def allFiles = new File(fromDir).listFiles() def numFiles = allFiles.length for (i in 0..(numFiles - 1)) tra

我对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)
}
现在,我试着将这段代码并行化如下:

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)
            }
        }
    }
}
在我的测试用例中,nunCores是4,numFiles是3。 这是怎么回事?

好的,两件事:

  • 在线程的隐式run()方法中,您正在引用“i”变量。我必须通过一个调试器来查看到底发生了什么,但从技术上讲,您甚至不应该在那里访问“I”,因为它不是最终的。因此,我建议创建一个可运行对象,在构造函数中向其传递“I”。然后在线程上启动runnable

  • Groovy有很好的并发支持——没有理由像这样使用自己的。看看


  • 您正在启动线程,但程序在运行之前就完成了

    如中所示,您需要对线程调用
    join
    ,等待线程完成

    使用executor框架可能更容易,它在同一页的下方显示


    编辑 只是为了好玩,我使用
    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' )
    
    //这将执行文件列表所需的任务
    def翻译(列表文件){
    文件。每个{
    //我们会把它打印出来,睡一会儿
    打印它
    线程。睡眠(300)
    }
    }
    //makeWorker返回将处理文件的闭包
    def makeWorker(列表文件){
    {->翻译(文件)}
    }
    //主要处理功能
    作废流程(列出文件){
    int numCores=Runtime.getRuntime().availableProcessors()
    //将要处理的文件拆分为组(每个工作人员一个)
    def分区=(0。。
    文件[(i.)。。
    Thread.start makeWorker(组)
    }
    //然后等待他们全部完成
    线程*.join()
    }
    //用字母a到z模拟该过程
    进程('a'..'z')
    
    您将有权访问
    i
    ,它不需要是Groovy中的final,但它很可能没有您想要的值require@greybeardedgeekGPars链接需要登录。@dbush-显然,那里有人改变了什么(我猜这与Groovy最近的转换有关
    // 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' )