Sunday, August 30, 2009

Puzzle 49 – Solution

With 49 (coincidence?) comments posted for the last puzzle – this was the most solved puzzle till date. There were a range of solutions and I have listed out the common solution below,

Solution 1- Use a Finalizer.

The simplest solution that one could use for this problem is to add a finalizer in the code that restores the looper object.

package com.twister; public class StopTheLoop { static StopTheLoop looper; public static void main(String[] args) { looper = new StopTheLoop(); looper = null; do{ System.out.println("Infinite Loop");; }while(looper==null); } @Override protected void finalize() throws Throwable { looper = this; } }

The hint to use this solution came from the fact the line -- first created a new Object and then the reference was set to null – which meant that when the garbage collector runs you had a chance to restore the object.

Solution 2 – Override the System.out with a custom object that exits, after doing a single print.

package com.twister; import java.io.PrintStream; public class StopTheLoop { static StopTheLoop looper; public StopTheLoop() { PrintStream ps = new PrintStream(System.out){ @Override public void println(String x) { super.println(x); System.exit(0); } }; System.setOut(ps); } public static void main(String[] args) { looper = new StopTheLoop(); looper = null; do{ System.out.println("Infinite Loop");; }while(looper==null); } }

Solution 3 – Creating a thread that exits or restores looper after some time or by checking if the looper reference is null and creating a new object.

package com.twister; public class StopTheLoop extends Thread { static StopTheLoop looper; static { new StopTheLoop().start(); } public static void main(String[] args) { looper = new StopTheLoop(); looper = null; do { System.out.println("Infinite Loop"); } while (looper == null); } @Override public void run() { Thread.yield(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.exit(0); } }

I think this about covers all the solutions for this puzzle.

2 comments:

  1. I do not fully agree with the simplest solution:
    1) It is not guaranteed that the JVM will leave the object execute the System.out.println piece of code. Very theoretically speaking, the object could be finalized before the first println would be completely executed.
    2) Attaching an instance that is going to be finalized to a static member if plain awful;
    3) You do not have control over the number of times the message is being print.

    I posted the second solution, which seemed to me technically speaking more sound.

    ReplyDelete
  2. Here is my 2 cents on the simplest solution :)

    1) It is not guaranteed that the JVM will leave the object execute the System.out.println piece of code. Very theoretically speaking, the object could be finalized before the first println would be completely executed.

    Sam - That’s possible but it still does not affect the solution - being a do-while it is guaranteed to execute at least once.

    2) Attaching an instance that is going to be finalized to a static member if plain awful;

    Sam - It is not really needed to attach the instance that is going to be garbage collected to the static member.
    You can just as easily have said looper = new StopTheLoop().

    3) You do not have control over the number of times the message is being print.

    Sam - Agree - The puzzle did not require you to control the number of times the message gets printed - as I said this was simple solution.

    ReplyDelete

Solution for this question?