问题:1000级台阶,一个人一步可以走2级也可以一步走1级,如果这个刚好把这1000级走完,那么有多少中走法?
思路如下:该问题就是N个红色球和M个黑色球的组合问题。假设一个黑色球代表1级台阶,一个红色球代表2级台阶,那么1000级台阶,就是M+2*N= 1000。然后根据

下面给出三种解题的程序,分别是单线程处理、fork-join框架处理、threadpool处理,大家也看看具体的性能
1、单线程
package louti;
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
public class LouTiWenTi {
public static final int MAX_NUM = 3000;// 楼梯总的台阶数
public static final int MAX_2_SETP_NUM = MAX_NUM / 2;// 一步走两级台阶,最大的步数
public static final int MAX_1_STEP_NUM = MAX_NUM;// 一步走一级台阶,最大的步数
public static void main(String ... args) {
System.out.println(MAX_NUM + "级台阶,一个人一步可以走2级台阶也可以一步走1级台阶,如果这个人刚好把这" + MAX_NUM + "级台阶走完,总共有多少种走法?步骤如下:");
long begin = System.currentTimeMillis();
BigInteger cnt = new BigInteger("0");
for (int step1, step2 = 0; step2 <= MAX_2_SETP_NUM; step2++) {
step1 = MAX_NUM - 2 * step2;
if (step1 >= step2) {
BigInteger sum = compute(step1 + 1, step2);
System.out.println("走" + step1 + "个一级台阶," + step2 + "个二级台阶.有" + sum + "种走法");
cnt = cnt.add(sum);
} else if (step2 > step1) {
BigInteger sum = compute(step2 + 1, step1);;
System.out.println("走" + step1 + "个一级台阶," + step2 + "个二级台阶.有" + sum + "种走法");
cnt = cnt.add(sum);
}
}
System.out.println("总共有" + cnt + "种走法.耗费"+(System.currentTimeMillis()-begin)+"毫秒");
}
public static BigInteger compute(int m, int n) {
if (m < n) {
throw new RuntimeException("入参m必须大于等于n");
}
if (n == 0) {
return new BigInteger("1");
}
int m_n = m - n;
List<Integer> mList = new LinkedList<Integer>();
List<Integer> nList = new LinkedList<Integer>();
List<Integer> m_nList = new LinkedList<Integer>();
if (m_n >= n) {
for (int i = m; i > m_n; i--) {
mList.add(i);
}
for (int i = 1; i <= n; i++) {
nList.add(i);
}
} else {
for (int i = m; i > n; i--) {
mList.add(i);
}
for (int i = 1; i <= (m - n); i++) {
m_nList.add(i);
}
}
// 做约分
if (nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < nList.size(); j++) {
if (Integer.parseInt(String.valueOf(mList.get(i))) == Integer.parseInt(String.valueOf(nList.get(j)))) {
mList.remove(i);
nList.remove(j);
i--;
break;
}
}
}
}
// 做约分
if (m_nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < m_nList.size(); j++) {
if (Integer.parseInt(String.valueOf(mList.get(i))) == Integer.parseInt(String.valueOf(m_nList.get(j)))) {
mList.remove(i);
m_nList.remove(j);
i--;
break;
}
}
}
}
// 做约分
if (nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < nList.size(); j++) {
int a = mList.get(i);
int b = nList.get(j);
int gys = gongyue(a, b);
if (gys > 1) {
nList.set(j, b / gys);
mList.set(i, a / gys);
}
}
}
}
// 做约分
if (m_nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < m_nList.size(); j++) {
int a = mList.get(i);
int b = m_nList.get(j);
int gys = gongyue(a, b);
if (gys > 1) {
m_nList.set(j, b / gys);
mList.set(i, a / gys);
}
}
}
}
// 阶乘分子
BigInteger fenzi = new BigInteger("1");
for (int i = 0; i < mList.size(); i++) {
fenzi = fenzi.multiply(new BigInteger(String.valueOf(mList.get(i))));
}
// 阶乘分母1
BigInteger fenmu1 = new BigInteger("1");
for (int i = 0; i < nList.size(); i++) {
fenmu1 = fenmu1.multiply(new BigInteger(String.valueOf(nList.get(i))));
}
// 阶乘分母2
BigInteger fenmu2 = new BigInteger("1");
for (int i = 0; i < m_nList.size(); i++) {
fenmu2 = fenmu2.multiply(new BigInteger(String.valueOf(m_nList.get(i))));
}
return fenzi.divide(fenmu1.multiply(fenmu2));
}
// 求最小公倍数
public static int gongbei(int a, int b) {
return (a * b) / gongyue(a, b);
}
// 求最大公约数函数
public static int gongyue(int a, int b) {
int gongyue = 0;
if (a < b) { // 交换a、b的值
a = a + b;
b = a - b;
a = a - b;
}
if (a % b == 0) {
gongyue = b;
}
while (a % b > 0) {
a = a % b;
if (a < b) {
a = a + b;
b = a - b;
a = a - b;
}
if (a % b == 0) {
gongyue = b;
}
}
return gongyue;
}
}
2、fork-join
package louti;
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
public class LouTiWenTiFockJoin extends RecursiveTask<BigInteger> {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final int MAX_NUM = 3000;// 楼梯总的台阶数
public static final int MAX_2_SETP_NUM = MAX_NUM / 2;// 一步走两级台阶,最大的步数
public static final int MAX_1_STEP_NUM = MAX_NUM;// 一步走一级台阶,最大的步数
public static final int MAX_TASK_NUM = 10;
public String[] taskArray;
public int start;
public int end;
public LouTiWenTiFockJoin(String[] taskArray, int start, int end) {
this.taskArray = taskArray;
this.start = start;
this.end = end;
}
@Override
protected BigInteger compute() {
BigInteger cnt = new BigInteger("0");
if (end - start < MAX_TASK_NUM) {
for (int i = start; i < end; i++) {
String[] mnStrArr = taskArray[i].split(",");
int m = Integer.parseInt(mnStrArr[0]);
int n = Integer.parseInt(mnStrArr[1]);
BigInteger result = new BigInteger("0");
if (m >= n) {
result = compute(m + 1, n);
System.out.println("走" + m + "个一级台阶," + n + "个二级台阶.有" + result + "种走法");
cnt = cnt.add(result);
} else if (m < n) {
result = compute(n + 1, m);
System.out.println("走" + m + "个一级台阶," + n + "个二级台阶.有" + result + "种走法");
cnt = cnt.add(result);
}
cnt.add(result);
}
return cnt;
} else {
int middle = (start + end) / 2;
LouTiWenTiFockJoin left = new LouTiWenTiFockJoin(taskArray, start, middle);
LouTiWenTiFockJoin right = new LouTiWenTiFockJoin(taskArray, middle, end);
left.fork();
right.fork();
return left.join().add(right.join());
}
}
public static BigInteger compute(int m, int n) {
if (m < n) {
throw new RuntimeException("入参m必须大于等于n");
}
if (n == 0) {
return new BigInteger("1");
}
int m_n = m - n;
List<Integer> mList = new LinkedList<Integer>();
List<Integer> nList = new LinkedList<Integer>();
List<Integer> m_nList = new LinkedList<Integer>();
if (m_n >= n) {
for (int i = m; i > m_n; i--) {
mList.add(i);
}
for (int i = 1; i <= n; i++) {
nList.add(i);
}
} else {
for (int i = m; i > n; i--) {
mList.add(i);
}
for (int i = 1; i <= (m - n); i++) {
m_nList.add(i);
}
}
// 做约分
if (nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < nList.size(); j++) {
if (Integer.parseInt(String.valueOf(mList.get(i))) == Integer.parseInt(String.valueOf(nList.get(j)))) {
mList.remove(i);
nList.remove(j);
i--;
break;
}
}
}
}
// 做约分
if (m_nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < m_nList.size(); j++) {
if (Integer.parseInt(String.valueOf(mList.get(i))) == Integer.parseInt(String.valueOf(m_nList.get(j)))) {
mList.remove(i);
m_nList.remove(j);
i--;
break;
}
}
}
}
// 做约分
if (nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < nList.size(); j++) {
int a = mList.get(i);
int b = nList.get(j);
int gys = gongyue(a, b);
if (gys > 1) {
nList.set(j, b / gys);
mList.set(i, a / gys);
}
}
}
}
// 做约分
if (m_nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < m_nList.size(); j++) {
int a = mList.get(i);
int b = m_nList.get(j);
int gys = gongyue(a, b);
if (gys > 1) {
m_nList.set(j, b / gys);
mList.set(i, a / gys);
}
}
}
}
// 阶乘分子
BigInteger fenzi = new BigInteger("1");
for (int i = 0; i < mList.size(); i++) {
fenzi = fenzi.multiply(new BigInteger(String.valueOf(mList.get(i))));
}
// 阶乘分母1
BigInteger fenmu1 = new BigInteger("1");
for (int i = 0; i < nList.size(); i++) {
fenmu1 = fenmu1.multiply(new BigInteger(String.valueOf(nList.get(i))));
}
// 阶乘分母2
BigInteger fenmu2 = new BigInteger("1");
for (int i = 0; i < m_nList.size(); i++) {
fenmu2 = fenmu2.multiply(new BigInteger(String.valueOf(m_nList.get(i))));
}
return fenzi.divide(fenmu1.multiply(fenmu2));
}
// 求最小公倍数
public static int gongbei(int a, int b) {
return (a * b) / gongyue(a, b);
}
// 求最大公约数函数
public static int gongyue(int a, int b) {
int gongyue = 0;
if (a < b) { // 交换a、b的值
a = a + b;
b = a - b;
a = a - b;
}
if (a % b == 0) {
gongyue = b;
}
while (a % b > 0) {
a = a % b;
if (a < b) {
a = a + b;
b = a - b;
a = a - b;
}
if (a % b == 0) {
gongyue = b;
}
}
return gongyue;
}
public static void main(String ... args) throws Exception {
System.out.println(MAX_NUM + "级台阶,一个人一步可以走2级台阶也可以一步走1级台阶,如果这个人刚好把这" + MAX_NUM + "级台阶走完,总共有多少种走法?步骤如下:");
long begin = System.currentTimeMillis();
String[] taskArr = new String[MAX_2_SETP_NUM + 1];
for (int step1, step2 = 0; step2 <= MAX_2_SETP_NUM; step2++) {
step1 = MAX_NUM - 2 * step2;
taskArr[step2] = step1 + "," + step2;
}
// 创建包含Runtime.getRuntime().availableProcessors()返回值作为个数的并行线程的ForkJoinPool
ForkJoinPool forkJoinPool = new ForkJoinPool();
// 提交可分解的PrintTask任务
LouTiWenTiFockJoin task = new LouTiWenTiFockJoin(taskArr, 0, taskArr.length);
Future<BigInteger> future = forkJoinPool.submit(task);
while (!task.isDone()) {
}
System.out.println("总共有" + future.get() + "种走法.耗费" + (System.currentTimeMillis() - begin) + "毫秒");
// 关闭线程池
forkJoinPool.shutdown();
}
}
3、threadpool
package louti;
import java.math.BigInteger;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class LouTiWenTiThreadPool {
public static final int MAX_NUM = 2000;// 楼梯总的台阶数
public static final int MAX_2_SETP_NUM = MAX_NUM / 2;// 一步走两级台阶,最大的步数
public static final int MAX_1_STEP_NUM = MAX_NUM;// 一步走一级台阶,最大的步数
public static void main(String ... args) throws Exception {
System.out.println(MAX_NUM + "级台阶,一个人一步可以走2级台阶也可以一步走1级台阶,如果这个人刚好把这" + MAX_NUM + "级台阶走完,总共有多少种走法?步骤如下:");
long begin = System.currentTimeMillis();
ExecutorService executor = Executors.newCachedThreadPool(Executors.defaultThreadFactory());
Future<BigInteger>[] futures = new Future[MAX_2_SETP_NUM + 1];
final CountDownLatch latch = new CountDownLatch(MAX_2_SETP_NUM + 1);
for (int step2 = 0; step2 <= MAX_2_SETP_NUM; step2++) {
int step1 = MAX_NUM - 2 * step2;
futures[step2] = (Future<BigInteger>)executor.submit(new Task(step1, step2, latch));
}
executor.shutdown();
latch.await();
BigInteger cnt = new BigInteger("0");
for (int i = 0; i < futures.length; i++) {
cnt = cnt.add(futures[i].get());
}
System.out.println("总共有" + cnt + "种走法.耗费" + (System.currentTimeMillis() - begin) + "毫秒");
}
static class Task implements Callable<BigInteger> {
private int m;
private int n;
private CountDownLatch latch;
public Task(int m, int n, CountDownLatch latch) {
this.m = m;
this.n = n;
this.latch = latch;
}
@Override
public BigInteger call() throws Exception {
BigInteger result = new BigInteger("0");
if (m >= n) {
result = compute(m + 1, n);
System.out.println("走" + m + "个一级台阶," + n + "个二级台阶.有" + result + "种走法");
} else if (m < n) {
result = compute(n + 1, m);
System.out.println("走" + m + "个一级台阶," + n + "个二级台阶.有" + result + "种走法");
}
this.latch.countDown();
return result;
}
public static BigInteger compute(int m, int n) {
if (m < n) {
throw new RuntimeException("入参m必须大于等于n");
}
if (n == 0) {
return new BigInteger("1");
}
int m_n = m - n;
List<Integer> mList = new LinkedList<Integer>();
List<Integer> nList = new LinkedList<Integer>();
List<Integer> m_nList = new LinkedList<Integer>();
if (m_n >= n) {
for (int i = m; i > m_n; i--) {
mList.add(i);
}
for (int i = 1; i <= n; i++) {
nList.add(i);
}
} else {
for (int i = m; i > n; i--) {
mList.add(i);
}
for (int i = 1; i <= (m - n); i++) {
m_nList.add(i);
}
}
// 做约分
if (nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < nList.size(); j++) {
if (Integer.parseInt(String.valueOf(mList.get(i))) == Integer.parseInt(String.valueOf(nList.get(j)))) {
mList.remove(i);
nList.remove(j);
i--;
break;
}
}
}
}
// 做约分
if (m_nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < m_nList.size(); j++) {
if (Integer.parseInt(String.valueOf(mList.get(i))) == Integer.parseInt(String.valueOf(m_nList.get(j)))) {
mList.remove(i);
m_nList.remove(j);
i--;
break;
}
}
}
}
// 做约分
if (nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < nList.size(); j++) {
int a = mList.get(i);
int b = nList.get(j);
int gys = gongyue(a, b);
if (gys > 1) {
nList.set(j, b / gys);
mList.set(i, a / gys);
}
}
}
}
// 做约分
if (m_nList.size() > 0) {
for (int i = 0; i < mList.size(); i++) {
for (int j = 0; j < m_nList.size(); j++) {
int a = mList.get(i);
int b = m_nList.get(j);
int gys = gongyue(a, b);
if (gys > 1) {
m_nList.set(j, b / gys);
mList.set(i, a / gys);
}
}
}
}
// 阶乘分子
BigInteger fenzi = new BigInteger("1");
for (int i = 0; i < mList.size(); i++) {
fenzi = fenzi.multiply(new BigInteger(String.valueOf(mList.get(i))));
}
// 阶乘分母1
BigInteger fenmu1 = new BigInteger("1");
for (int i = 0; i < nList.size(); i++) {
fenmu1 = fenmu1.multiply(new BigInteger(String.valueOf(nList.get(i))));
}
// 阶乘分母2
BigInteger fenmu2 = new BigInteger("1");
for (int i = 0; i < m_nList.size(); i++) {
fenmu2 = fenmu2.multiply(new BigInteger(String.valueOf(m_nList.get(i))));
}
return fenzi.divide(fenmu1.multiply(fenmu2));
}
// 求最小公倍数
public static int gongbei(int a, int b) {
return (a * b) / gongyue(a, b);
}
// 求最大公约数函数
public static int gongyue(int a, int b) {
int gongyue = 0;
if (a < b) { // 交换a、b的值
a = a + b;
b = a - b;
a = a - b;
}
if (a % b == 0) {
gongyue = b;
}
while (a % b > 0) {
a = a % b;
if (a < b) {
a = a + b;
b = a - b;
a = a - b;
}
if (a % b == 0) {
gongyue = b;
}
}
return gongyue;
}
}
}
以下是台阶数目为1000、2000、3000在同一机器环境下的性能对比。单位(毫秒)
1000 | 2000 | 3000 | |
单线程 | 2740 | 34808 | 168578 |
forkjoin | 1759 | 13180 | 61389 |
threadpool | 1651 | 13277 | 11120 |