java多线程计算汉诺塔
时间: 2023-06-30 22:18:00 浏览: 45
下面是一个使用 Java 多线程计算汉诺塔的示例代码:
```java
public class HanoiTower {
private static final int NUM_DISKS = 3;
private static final int NUM_PEGS = 3;
public static void main(String[] args) {
HanoiSolver solver = new HanoiSolver(NUM_DISKS, NUM_PEGS);
solver.solve();
}
private static class HanoiSolver {
private final int numDisks;
private final int numPegs;
private final List<Stack<Integer>> pegs;
private final AtomicInteger numMoves;
public HanoiSolver(int numDisks, int numPegs) {
this.numDisks = numDisks;
this.numPegs = numPegs;
this.pegs = new ArrayList<>();
for (int i = 0; i < numPegs; i++) {
pegs.add(new Stack<>());
}
for (int i = numDisks; i >= 1; i--) {
pegs.get(0).push(i);
}
this.numMoves = new AtomicInteger(0);
}
public void solve() {
executeTask(new HanoiTask(numDisks, 0, 1, 2));
}
private void executeTask(HanoiTask task) {
if (task.numDisks == 1) {
moveSingleDisk(task.fromPeg, task.toPeg);
} else {
int newPeg = getNewPeg(task.fromPeg, task.toPeg);
executeTask(new HanoiTask(task.numDisks - 1, task.fromPeg, newPeg, task.toPeg));
moveSingleDisk(task.fromPeg, task.toPeg);
executeTask(new HanoiTask(task.numDisks - 1, newPeg, task.toPeg, task.fromPeg));
}
}
private void moveSingleDisk(int fromPeg, int toPeg) {
int disk = pegs.get(fromPeg).pop();
pegs.get(toPeg).push(disk);
System.out.println("Move disk " + disk + " from peg " + fromPeg + " to peg " + toPeg);
numMoves.incrementAndGet();
}
private int getNewPeg(int fromPeg, int toPeg) {
for (int i = 0; i < numPegs; i++) {
if (i != fromPeg && i != toPeg) {
return i;
}
}
throw new IllegalStateException("No available peg");
}
private class HanoiTask {
private final int numDisks;
private final int fromPeg;
private final int toPeg;
private final int viaPeg;
public HanoiTask(int numDisks, int fromPeg, int toPeg, int viaPeg) {
this.numDisks = numDisks;
this.fromPeg = fromPeg;
this.toPeg = toPeg;
this.viaPeg = viaPeg;
}
}
}
}
```
这里的 `HanoiSolver` 类使用一个 `Stack` 对象来表示每个针上的盘子,并使用 `AtomicInteger` 对象来记录移动次数。`HanoiTask` 类表示需要移动的盘子数量以及移动的起始针、目标针和中间针。在 `executeTask()` 方法中,如果任务中只有一个盘子,就直接将盘子从起始针移动到目标针;否则,先将任务拆分成三个子任务,分别将 `numDisks - 1` 个盘子从起始针移动到中间针,将一个盘子从起始针移动到目标针,最后再将 `numDisks - 1` 个盘子从中间针移动到目标针。