我有两个数组abc[100]
和def[1000]
,我必须找到一个数组xyz[100]
,其中xyz[i] = minDistance(abc[i],def)
即abc
中的每个元素我必须在def
中找到相应的最近元素,并在xyz.
为此,我使用两级线程。在第一级,我在abc
中为每10个点创建线程,在每个10点创建线程,我在def.
每100个点创建子线程。下面是我的实现。
我的问题是
如何等待abc
(即def
个线程)的子线程。我已经完成了java连接方法,但无法弄清楚如何使用它。
在这种情况下我可以使用循环屏障。
abc
的实际数据大小为1000,def
的实际数据为10000,我之前没有使用过线程,因此这个实现可能会出现任何问题。我也看到在某些示例中使用了ThreadPoolExecutor
而不是FixedThreads
,但无法确定ThreadPoolExecutor
会有多少。
1。 DistanceCalculation
public class MinDistanceCalculation {
public static List<double[]> xyz = new Vector<double[]>();
public void method1(){
double[][] abc = new double[100][7];
double[][] def = new double[1000][7];
ExecutorService executorService = Executors.newFixedThreadPool(10);
for(int i = 0 ; i < abc.length ; i = i*10){
executorService.execute(new MainThread(abc,i , i*10 , def));
}
}
}
2。主线程/ abc线程
public class MainThread implements Runnable{
double[][] abc = null;
double[][] def = null;
int startPos = 0;
int endPos = 0;
public MainThread(double[][] abc , int startPos , int endPos, double[][] def){
this.abc = abc;
this.def = def;
}
@Override
public void run() {
for(int i = startPos ; i < endPos ; i++){
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<Future<double[]>> minDistancePoints = new ArrayList<Future<double[]>>();
for(int j = 0 ; j < def.length ; j = j*100 ){
Future<double[]> minDistancePoint = null;
minDistancePoint = executorService.submit(new ChildThread(abc[i], def, j, j*100));
minDistancePoints.add(minDistancePoint);
}
// How can I wait for all the threads and calculate the MinDistance and
//add it to the actual array
findMinDistanceOfAll(abc[i],minDistancePoints);
executorService.shutdown();
}
}
public void findMinDistanceOfAll(double[] mainPoint, List<Future<double[]>> distancePoints){
// Here I will find the min among the given points and add it actual array.
MinDistanceCalculation.xyz.add(null);
}
}
子线程/ def线程
public class ChildThread implements Callable<double[]> {
double[] abc = null;
double[][] def = null;
int from;
int to;
public ChildThread(double[] abc, double[][] def, int from, int to) {
this.def = def;
this.abc = abc;
this.from = from;
this.to = to;
}
@Override
public double[] call() throws Exception {
double minDistance = Double.MAX_VALUE;
double currentDistance = 0;
double[] minCandidate = null;
for (int i = from; i < to; i++) {
currentDistance = distance(abc,def[i]);
if (currentDistance < minDistance) {
minDistance = currentDistance;
minCandidate = def[i];
}
}
return minCandidate;
}
public double distance(double[] point1 , double[] point2) {
// Calculates and Returns Euclidean distance
return 0;
}
}
答案 0 :(得分:1)
确定并行任务应该执行的操作。最佳并行化是在交互最少的情况下。因此,计算xyz数组的一个元素是最佳候选。在10个块中拆分def很糟糕,因为这些块不是独立的。当我们想要增加任务的大小并因此减少任务的交互时,在一个线程中组合abc的10个元素可能有意义,但这是一个不明显的优化,应该在以后完成。
决定如何运行这些任务。将每个任务包装在单独的Runnable中并提交到线程池是一种通用的方法,但在这里我们可以避免这种情况。每个大头钉都由索引标识为abc数组(和xyz数组)。我们可以将当前索引保存在AtomicInteger中,并使用getAndIncrement获取下一个索引。
由于此任务受CPU约束,因此启动N个线程,其中N =可用处理器的数量。
使用CountDownLatch计算已完成任务的数量。
在此处添加一些初始化和最小距离计算:
public class MinDistanceCalculation implements Runnable {
AtomicInteger idx=new AtomicInteger();
int inpSize=100;
double[] abc = new double[inpSize];
double[] def = ...
double[] xyz = new double[inpSize];
CountDownLatch counter=new CountDownLatch(inpSize);
public void run() {
for (;;) {
int nextIndex=idx.getAndIncrement();
if (nextIndex>=inpSize) return;
xyz[nextIndex]=minDistance(abc[nextIndex], def);
counter.countDown();
}
void start() {
for (int k=0; k<Runtime.getRuntime.availableProcessors()) {
new Thread(this).start();
}
counter.await();
}
public static void main(String[] a) {
new MinDistanceCalculation().start();
}
}