我正在用java编写一些计算代码,我需要将整个计算限制在特定数量的线程上运行(取决于有多少内核可用以及允许占用多少内核)。很多计算都涉及适合并行处理的任务。假设我对这样一个复杂的计算有如下设置。
class ComplexOpA implements Function<double[], double[]> {
@Inject ExecutorService threadPool;
/**
* Factory returns a Function<Double,Double> to call on each element
* of an input array
*/
@Inject ElementOperationFactory opFactory;
double[] apply(double[] input) {
int[] indices = int[input.length];
for (int i = 0; i < input.length; i++)
indices[i] = i;
// Same operations need to be done on each element of `input`
double[] output = new double[input.length];
threadPool.invokeAll(createCallables(indices, i -> {
double iInput = input[i];
double iOutput = opFactory.createOperation().calculate(iInput);
output[i] = iOutput;
})
}
List<Callable<Void>> createCallables(
int[] indices,
Consumer<Integer> elementOperation){
// Create list of Callable<Void> that can be passed to
// the executor service.
}
}
假设 Function
由供应商提供 ElementOperationFactory
没有尝试多线程执行,这将正常运行,没有任何问题。但是,如果元素函数本身的编写方式也使用相同的线程池来运行涉及并行处理的计算,则可能会出现死锁情况。例如,
class ElementOpA implements Function<Double, Double> {
@Inject ExecutorService threadPool;
public double apply(double input) {
/*
* Assume there is a further complex operation here that the programmer
* attempted to speed-up using multi-threading.
*/
threadPool.invokeAll(...);
}
}
在这种情况下,我们遇到了这样一个问题:线程池中固定数量的线程可能都会阻塞单个元素操作以完成,但没有其他线程可供元素操作中涉及的子任务执行,从而导致它们无限期阻塞。
有人能提出一种方法来避免这种潜在的障碍吗?
一些条件:
无法知道正在执行的任何操作在这些计算中需要多长时间。因此,使用超时是不可行的。
无法判断在哪个嵌套操作级别,程序员可能试图使用线程池进行并行处理。所执行的计算是复杂的,根据具体用途,同一操作有几种可能的实现。
有一个公共线程池,任何试图使用它进行并行处理的操作都可以访问和使用它。
暂无答案!
目前还没有任何答案,快来回答吧!