Java简单递归算法,使其并行
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java简单递归算法,使其并行相关的知识,希望对你有一定的参考价值。
我有一个简单的递归算法,该算法生成字符串的所有排列并计算通过一些条件的排列数。我想通过并行编程使其更高效,但是我不能将其与“ forkJoinPool”一起使用(我不确定,但是不可能用分而治之的方式来实现它)。因此,我不得不在分离的线程上运行所有计算(检查条件和递增计数器),但这并不比顺序算法更好。
Thread thread = new Thread(() -> {
compute(elements);
});
thread.start();
上面的代码似乎不能更好地工作。
package com.company;
public class Main {
public static void main(String[] args) {
long start = System.nanoTime();
call();
long end = System.nanoTime();
System.out.println((end - start) / 1000000);
}
private static void call() {
char[] elements = "1234567890+/".toCharArray();
Permutation p = new Permutation();
p.printAllRecursive(elements.length, elements);
System.out.println(p.counter);
}
}
class Permutation {
Integer counter = 0;
public void printAllRecursive(int n, char[] elements) {
if (n == 1) {
// running compute() in parallel
Thread thread = new Thread(() -> {
compute(elements);
});
thread.start();
} else {
for (int i = 0; i < n - 1; i++) {
printAllRecursive(n - 1, elements);
if (n % 2 == 0) {
swap(elements, i, n - 1);
} else {
swap(elements, 0, n - 1);
}
}
printAllRecursive(n - 1, elements);
}
}
private void swap(char[] elements, int a, int b) {
char tmp = elements[a];
elements[a] = elements[b];
elements[b] = tmp;
}
private void compute(char[] elements) {
String string = new String(elements);
int index1 = string.indexOf('/');
int index2 = string.indexOf('+');
if (index1 > 0 && index2 > 0 && index1 < 11 && index2 < 11) {
if (index1 > index2) {
if (index1 - index2 != 1) {
counter++;
}
}
}
}
}
方法compute(elements)非常耗时,如何在多线程中使其更高效?在此先感谢
[当您调用printAllRecursive()
时,您会创建一个附加线程来调用compute()
,然后再调用printAllRecursive()
并再次创建一个新线程。附加线程对您没有帮助。 似乎您的算法是错误的。
查看正确的代码以计算排列:
public class Main {
public static void main(String[] args) {
long start = System.nanoTime();
call();
long end = System.nanoTime();
System.out.println("time: " + (end - start) / 1000000);
}
private static void call() {
char[] elements = "ABCD".toCharArray();
int n = elements.length;
Permutation p = new Permutation();
p.printAllRecursive(elements, 0 , n-1);
System.out.println("number of permutations: " + p.counter);
}
}
class Permutation {
Integer counter = 0;
public void printAllRecursive(char[] elements, int l, int r) {
if (l == r) {
counter++;
//System.out.println(String.valueOf(elements));
} else {
for (int i = l; i <= r; i++) {
swap(elements, l, i);
printAllRecursive(elements, l+1, r);
swap(elements, l, i);
}
}
}
private void swap(char[] elements, int a, int b) {
char tmp = elements[a];
elements[a] = elements[b];
elements[b] = tmp;
}
}
您可以看到此算法的插图以更好地理解它,例如here
P.S。如前所述,您的问题不是多线程,但无论如何,我描述了为什么您不能简单地添加以下代码:
Thread thread = new Thread(() -> {
compute(elements);
});
thread.start();
您应该意识到的第一件事是,您不能通过不同的线程来修改一个内存区域。在您的代码示例中,您从不同的线程修改了字段counter
和数组elements
。为什么不能从不同线程修改一个变量?例如,线程1想要将序列'777777777'
写入您的数组。在此写入过程中,thread2希望从数组中读取值。因此,线程2可以读取值'777456789'
,因为线程1仍将数据写入数组并且尚未完成。因此,我们可以通过线程安全的Integer
更改AtomicInteger
并将synchronized
添加到swap
方法的签名。
以上是关于Java简单递归算法,使其并行的主要内容,如果未能解决你的问题,请参考以下文章