Java 简单Groovy线程管理器
我用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
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
。