我是Java的初学者,作为我的家庭作业,我应该为旅行商问题(here)发布的遗传算法解决方案实现并发。我们的目标是通过线程执行染色体评估。所以我的猜测是我必须重写这部分代码才能成为多线程:
// Gets the best tour in the population
public Tour getFittest() {
Tour fittest = tours[0];
// Loop through individuals to find fittest
for (int i = 1; i < populationSize(); i++) {
if (fittest.getFitness() <= getTour(i).getFitness()) {
fittest = getTour(i);
}
}
return fittest;
}
// Gets population size
public int populationSize() {
return tours.length;
}
最初,我打算手动拆分Array beetwen线程,但我认为这不是解决该问题的最佳方法。因此,我进行了一些研究,每个人都建议使用并行流或ExecutorService。但是,即使我试图模仿其他线程中发布的示例,也无法同时使用这两种解决方案。所以我的问题是:在这种情况下,我该如何精确实施它们?哪个更快?
编辑:对不起,我忘记发布尝试过的解决方案。在这里:
public Tour getFittest() {
Tour fittest = tours[0];
synchronized (fittest) {
final ExecutorService executor = Executors.newFixedThreadPool(4);
final List<Future<?>> futures = new ArrayList<>();
for (int i = 1; i < populationSize(); i++) {
Future<?> future = executor.submit((Runnable) () -> {
if (fittest.getFitness() <= getTour(i).getFitness()) {
fittest = getTour(i);
}
});
futures.add(future);
}
try {
for (Future<?> future : futures) {
future.get();
}
}catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
return fittest;
}
public int populationSize() {
return tours.length;
}
但是,当尝试运行它时,我在行中收到“在封闭范围内定义的局部变量fittest必须是最终的或实际上是最终的”错误:
fittest = getTour(i);
而且我不知道它为什么会发生,或者如何解决它,因为在初始化它时添加final关键字并不能解决它。除此之外,我对在此解决方案中使用synced关键字有一些疑问。我相信要实现真正的多线程,由于各种线程共享资源,因此需要使用它。我对吗?遗憾的是,我没有保留使用流的尝试,但是我很难理解它的工作原理。
Edit2:通过添加两个解决方法,我设法“解决”了我的解决方案。目前,我的代码如下:
public Tour getFittest() {
Tour fittest = tours[0];
synchronized (fittest) {
final ExecutorService executor = Executors.newFixedThreadPool(4);
final List<Future<?>> futures = new ArrayList<>();
for (int i = 1; i < populationSize(); i++) {
final Integer innerI = new Integer(i);
Future<?> future = executor.submit((Runnable) () -> {
if (fittest.getFitness() <= getTour(innerI).getFitness()) {
setFitness(innerI, fittest);
}
}
);
futures.add(future);
}
try {
for (Future<?> future : futures) {
future.get();
}
}catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
return fittest;
}
public int populationSize() {
return tours.length;
}
public Tour setFitness (int i, Tour fittest) {
fittest = getTour(i);
return fittest;
}
也就是说,在编译时有两个问题。程序运行的每秒内存使用率在不断提高,在大约十秒钟的时间内我的16GB RAM达到了最大值,而变量“ fittest”却完全没有改变。所以我想我还是在做错事。
答案 0 :(得分:0)
这是我的蒸汽实现:
private static Tour getFittest(Tour[] tours){
List<Map.Entry<Tour,Double>> lengths = new ArrayList<>();
Arrays.stream(tours).parallel().forEach(t->lengths.add(new AbstractMap.SimpleEntry<Tour,Double>(t,t.getLength())));
return Collections.min(lengths,Comparator.comparingDouble(Map.Entry::getValue)).getKey();
}
根据您的定义,进一步寻找可以是1衬套
private static Tour getFittest(Tour[] tours) {
return Arrays.stream(tours).parallel().map(t -> new AbstractMap.SimpleEntry<Tour, Double>(t, t.getLength()))
.min(Comparator.comparingDouble(Map.Entry::getValue)).get().getKey();
}
在进一步查看之后,他们使用了.getFitness(),它是长度的倒数。如果使用它,则使用.max()作为过滤器。
审查后实际上甚至更好
return Arrays.stream(tours).parallel()
.min(Comparator.comparingDouble(Tour::getLength)).get();