Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 简单Groovy线程管理器_Java_Multithreading_Groovy_Thread Safety - Fatal编程技术网

Java 简单Groovy线程管理器

Java 简单Groovy线程管理器,java,multithreading,groovy,thread-safety,Java,Multithreading,Groovy,Thread Safety,我用Groovy编写了一个小线程管理器。管理器获取数组、要在数组上执行的任务和块大小。然后在单独的线程中执行任务,并将结果添加到结果数组中 这是类代码: class ParallelManager { static def _threads = [] static def _threadsFinishedCorrectly = [] static def _results = [] static def runParallelTask( def dataArray, def

我用Groovy编写了一个小线程管理器。管理器获取数组、要在数组上执行的任务和块大小。然后在单独的线程中执行任务,并将结果添加到结果数组中

这是类代码:

class ParallelManager {

  static def _threads = []
  static def _threadsFinishedCorrectly = []
  static  def _results = []

  static def runParallelTask( def dataArray, def taskFunc, int chunkSize ){
    assert chunkSize > 0
    assert taskFunc
    if (dataArray.size()==0) return

    assert dataArray.size() >= 0

    def subArray = partitionArray(dataArray, chunkSize)
    assert subArray.size() > 0

    subArray.each{ arrChunk->
        _threads.add( Thread.start{

            def chunkResults = taskFunc(arrChunk)
            assert chunkResults != null 
            _results.add(chunkResults) // EXCEPTION HERE
            _threadsFinishedCorrectly.add(true)
        })
    }

    // wait for all threads to finish
    _threads.each{ it.join() }
    log.info("Waiting for all threads to finish...")

    assert _threadsFinishedCorrectly.size() == _threads.size(),'some threads failed.'
    assert _results.size() == _threads.size() 
    log.info("${_threads.size()} finished.")

    return _results
}

/**
* Util function
* @param array
* @param size
* @return
*/
  static def partitionArray(array, size) {
   def partitions = []
   int partitionCount = array.size() / size

   partitionCount.times { partitionNumber ->
       def start = partitionNumber * size
       def end = start + size - 1
       partitions << array[start..end]
   }

   if (array.size() % size) partitions << array[partitionCount * size..-1]
   return partitions
}
此代码偶尔会在上面标记的行引发此异常:

 Exception in thread "Thread-3" java.lang.ArrayIndexOutOfBoundsException: 1
 [java]     at java.util.ArrayList.add(ArrayList.java:352)
 [java]     at java_util_List$add.call(Unknown Source)
您有解决此问题的方法吗?我认为,像这样的一个小线程管理器对于许多人来说是非常有用的,它可以加速代码中的常见任务

干杯, 穆隆

你听说这个项目了吗?它是一个经过验证的库,旨在使多核硬件的并发编程更直观。它在收集处理方面非常强大

我建议您使用这个库,而不是实现自己的有限版本的简单线程管理器。

您听说过这个项目吗?它是一个经过验证的库,旨在使多核硬件的并发编程更直观。它在收集处理方面非常强大


我建议您使用此库,而不是实现您自己的有限版本的简单线程管理器。

使用GPAR可以这样做:

@Grab( 'org.codehaus.gpars:gpars:0.12' )
import groovyx.gpars.*

def arr = [ 1, 2, 3, 4, 5, 6, 7, 8 ]

arr = GParsPool.withPool {
  arr.collectParallel { it * 2 }
}

以下是使用GPAR的方法:

@Grab( 'org.codehaus.gpars:gpars:0.12' )
import groovyx.gpars.*

def arr = [ 1, 2, 3, 4, 5, 6, 7, 8 ]

arr = GParsPool.withPool {
  arr.collectParallel { it * 2 }
}

我用向量而不是数组列表解决了这个问题。 工作代码如下:

class ParallelManager {

static def log = Logger.getLogger(ParallelManager)

Vector _threads = []
Vector _threadsFinishedCorrectly = []
Vector _results = []

/**
 * 
 * @param dataArray
 * @param chunkSize
 * @param taskFunc
 * @return
 */
def runParallelTasks( def dataArray, int chunkSize, def taskFunc ){
    reset()
    assert chunkSize > 0
    assert taskFunc
    if (dataArray.size()==0) return

    assert dataArray.size() >= 0

    def subArray = partitionArray(dataArray, chunkSize)
    assert subArray.size() > 0

    subArray.each{ arrChunk->
        _threads.add( Thread.start{

            def chunkResults = taskFunc(arrChunk)
            assert chunkResults != null 
            _results.add(chunkResults)
            _threadsFinishedCorrectly.add(true)
        })
    }

    // wait for all threads to finish
    _threads.each{ it.join() }
    log.debug("Waiting for all threads to finish...")

    assert _threadsFinishedCorrectly.size() == _threads.size(),'some threads failed.'
    assert _results.size() == _threads.size() 
    log.debug("${_threads.size()} finished.")
    def res = _results.flatten()    
    //reset()
    assert dataArray.size() == res.size(),"Something went wrong. Some threads did not return their results. results=$res" 
    return res
}

void reset(){
    _threads = []
    _results = []
    _threadsFinishedCorrectly = []
}

/**
*
* @param array
* @param size
* @return
*/
def partitionArray(array, size) {
   def partitions = []
   int partitionCount = array.size() / size

   partitionCount.times { partitionNumber ->
       def start = partitionNumber * size
       def end = start + size - 1
       partitions << array[start..end]
   }

   if (array.size() % size) partitions << array[partitionCount * size..-1]
   return partitions
  }
}

我用向量而不是数组列表解决了这个问题。 工作代码如下:

class ParallelManager {

static def log = Logger.getLogger(ParallelManager)

Vector _threads = []
Vector _threadsFinishedCorrectly = []
Vector _results = []

/**
 * 
 * @param dataArray
 * @param chunkSize
 * @param taskFunc
 * @return
 */
def runParallelTasks( def dataArray, int chunkSize, def taskFunc ){
    reset()
    assert chunkSize > 0
    assert taskFunc
    if (dataArray.size()==0) return

    assert dataArray.size() >= 0

    def subArray = partitionArray(dataArray, chunkSize)
    assert subArray.size() > 0

    subArray.each{ arrChunk->
        _threads.add( Thread.start{

            def chunkResults = taskFunc(arrChunk)
            assert chunkResults != null 
            _results.add(chunkResults)
            _threadsFinishedCorrectly.add(true)
        })
    }

    // wait for all threads to finish
    _threads.each{ it.join() }
    log.debug("Waiting for all threads to finish...")

    assert _threadsFinishedCorrectly.size() == _threads.size(),'some threads failed.'
    assert _results.size() == _threads.size() 
    log.debug("${_threads.size()} finished.")
    def res = _results.flatten()    
    //reset()
    assert dataArray.size() == res.size(),"Something went wrong. Some threads did not return their results. results=$res" 
    return res
}

void reset(){
    _threads = []
    _results = []
    _threadsFinishedCorrectly = []
}

/**
*
* @param array
* @param size
* @return
*/
def partitionArray(array, size) {
   def partitions = []
   int partitionCount = array.size() / size

   partitionCount.times { partitionNumber ->
       def start = partitionNumber * size
       def end = start + size - 1
       partitions << array[start..end]
   }

   if (array.size() % size) partitions << array[partitionCount * size..-1]
   return partitions
  }
}

不确定如何在Groovy中设置锁,但需要锁定所有线程更新共享集合的区域。我想我使用向量而不是ArrayList解决了这个问题。与ArrayList不同,向量似乎是同步的。它还没有崩溃:-)不确定如何在Groovy中设置锁,但需要锁定所有线程更新共享集合的区域。我想我通过使用向量而不是ArrayList解决了这个问题。与ArrayList不同,向量似乎是同步的。它还没有崩溃:-)是的,我看到了那个项目,但我在寻找一个基本的、简单的解决方案。@Mulone添加了一个答案,向您展示了GParsOw的基本和简单是的,我看到了那个项目,但我在寻找一个基本的、简单的解决方案。@Mulone添加了一个答案,向您展示了GParsOw的基本和简单,这很容易。顺便说一句,我的向量解决方案也很好。哇,很简单。顺便说一句,我的向量解决方案也很好。您可以通过使用
Collections.synchronizedCollection()
Vector
替换为任何集合类,方法是使用
Collections.synchronizedCollection()
将其包装为
Vector