转载

Java谜题3:汽车 - 解决方案

让我们看看如何让升级后的汽车打破速度限制。

<b>package</b> car;
  
<b>public</b> <b>final</b> <b>class</b> Car {
    <b>private</b> <b>final</b> <b>int</b> MAX_SPEED = 100;
  
    <b>private</b> <b>int</b> speed = 0;
  
    <b>public</b> <b>synchronized</b> <b>void</b> accelerate(<b>int</b> acceleration) {
        speed += acceleration;
        <b>if</b> (speed > MAX_SPEED)
            crash();
    }
  
    <b>public</b> <b>synchronized</b> <b>void</b> crash() {
        speed = 0;
    }
  
    <b>public</b> <b>synchronized</b> <b>void</b> vroom() {
        <b>if</b> (speed > MAX_SPEED * 10) {
            <font><i>// The goal is to reach this line</i></font><font>
            System.out.println(</font><font>"Vroom!"</font><font>);
        }
    }
}
</font>

给所有赛车手的教训是:我们希望赛车加速很多(speed += acceleration必须执行),但不要在撞到树并完全停止的地方执行(speed = 0不得执行)。

这两种陈述之间会发生什么?if(speed>max_speed)对我们没有任何帮助,因为speed确实需要高于max_speed。所以剩下的就是对crash()方法的调用。那一个必须失败:我们想要crash()崩溃!

我们可以通过确保堆栈上没有足够的空间来调用任何方法来实现。如果调用accelerate时堆栈几乎已满,则调用crash()时会出现stackOverflowerRor。我们怎么才能让这堆东西都快满了呢?一种方法是强制它:一种无限递归的方法,不断尝试。

<b>package</b> driver;
 
<b>import</b> car.Car;
 
<b>public</b> <b>class</b> Driver {
    <b>private</b> <b>static</b> Car car = <b>new</b> Car();
     
    <b>public</b> <b>static</b> <b>void</b> main(String args[]) {
        <b>try</b> {
            recurse();
        } <b>catch</b> (StackOverflowError e) {
        }
         
        car.vroom();
    }
     
    <b>public</b> <b>static</b> <b>void</b> recurse() {
        car.accelerate(1001);
        recurse();
    }
}

起效了!…至少在某些系统上。这里的一个问题是,如果你试图加速这么多并继续崩溃(在我的系统崩溃1500次之后),jvm会做一些汽车制造商从未做过的事情:它优化汽车,以确保它能够很快崩溃。它把对crash()的调用排成一行,将其本质上减少为if(speed>max_speed)speed=0;。这样就消除了stackoverflower错误的可能性。

我们可以通过稍微温和些来解决这个问题:少些崩溃,因此JVM不会决定优化它。首先增加堆栈直到它接近需要的位置,然后才将汽车添加到程式中。但知道你接近极限的唯一方法就是击中它。因此,我们在没有汽车的情况下递归,直到我们遇到堆栈溢出,然后向后退几步,再应用上面的强制解决方案:

<b>package</b> driver;
 
<b>import</b> car.Car;
 
<b>public</b> <b>class</b> Driver {
    <b>static</b> Car car = <b>new</b> Car();
    <b>static</b> <b>int</b> a = 0;
 
    <b>public</b> <b>static</b> <b>void</b> main(String args[]) {
        recurse();
        car.vroom();
    }
 
    <b>static</b> <b>void</b> recurse() {
        <b>try</b> {
            recurse(); <font><i>// recurse without the car</i></font><font>
        } <b>catch</b> (StackOverflowError e) {
            </font><font><i>// when we've hit the limit of the stack, just go back out</i></font><font>
        }
        <b>if</b> (a++ == 10) { </font><font><i>// after taking 10 steps back</i></font><font>
            recurse2(); </font><font><i>// recurse with the car</i></font><font>
        }
    }
 
    <b>static</b> <b>void</b> recurse2() {
        car.accelerate(1001);
        recurse2();
    }
}
</font>

另一种解决方案是使用Thread.stop。但是很难把时间计算得恰到好处; 它在整个系统中不可靠。

原文  https://www.jdon.com/53130
正文到此结束
Loading...