Java謎題1:小丑 - 解決方案

jdon發表於2019-09-18

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



 

相關文章