Java谜题1:小丑 - 解决方案

19-09-18 jdon

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();
        }
    }
}

 

    

猜你喜欢