package clowns; import java.util.HashSet; import java.util.Set; public class Volkswagen { private static final int CAPACITY = 5; private Set<Clown> clowns = new HashSet<Clown>(); public synchronized void add(Clown clown) { if (clowns.size() >= CAPACITY) { throw new IllegalStateException("I'm full"); } else { clowns.add(clown); } } public synchronized void done() { if (clowns.size() == 20) { // The goal is to reach this line System.out.println("I'm a Volkswagen with 20 clowns!"); } } }
|
解决方案的路径
想象一下这是一辆真正的车,里面有真正的小丑。
–不可能让20个小丑进来!只有五个安全带,这辆大众汽车真的坚持安全。当小丑进来时,它首先检查里面是否还没有五个人。只有在检查之后,它才允许另一个人坐(小丑。添加(小丑))。只要有五个小丑坐着,就没办法再通过检查了,所以就没办法再增加小丑了。
–你说得对,我们不能一个一个地添加它们。但在他们进车时的检查和他们真正坐下之间,有一个机会之窗。让二十个小丑同时上车。他们都将通过大众汽车的检查,因为它只计算已经坐下来的小丑。只有在检查之后他们才能坐下来。
–这辆车的synchronized保护装置防止其他人在检查和坐下之间对它做任何事情。
–事实上,它阻止了其他人的干涉。这并不妨碍大众汽车或小丑自己去做,如果他们有机会(在同一个线程上)。
–但他们没有得到这个机会; 这辆车是一个控制狂。检查后立即让他们坐在座位上(在Set)。
–你看过这些座位了吗?他们已被编号,他们总是首先询问一个人想要坐哪个号码(.hashCode())。我们在这里有一些奇怪的小丑:当他们有机会决定时,在回答之前,他们可以迅速将另一个小丑拉进车里。然后那个小丑与另一个小丑完全一样。这种情况一直存在,直到有一堆二十个人递归地互相拉扯。只要他们的屁股不碰到座位,安全带标志就不会亮。
–那一定很壮观。
解决方案
递归调用volkswagen.add,方法是重写clown.hashcode():
package you; import clowns.Clown; import clowns.Volkswagen; public class You { static int counter = 0; static Volkswagen vw = new Volkswagen(); public static void main(String args[]) { vw.add(new RecursiveClown()); vw.done(); } static class RecursiveClown extends Clown { public int hashCode() { if (++counter < 20) { vw.add(new RecursiveClown()); } return super.hashCode(); } } }
|