class Results
{
    private boolean []working;
    private int []results;

    Results ( int Size )
    {
	working = new boolean [Size];
	results = new int [Size];
	for ( int i=2; i < Size; i++ ) {
	    working[i] = false;
	    results[i] = -1;
	}
	working[0] = true;
	working[1] = true;
	results[0] = 1;
	results[1] = 1;
    }

    synchronized void put (int value, int target)
    {
	results[target] = value;
	working[target] = true;
    }

    synchronized int get (int target)
    {
	if ( working [target] && results[target] >= target ) 
	    return results[target];
	else 
	    return -1;
    }

    synchronized boolean done( int target )
    {
	if ( target > -1 )
	    return working [target];
	else 
	    return true;
    }

    synchronized void start_work( int target )
    {
	working [target] = true;
    }

    

}


class T_Fib extends Thread
{
    private Results results;
    int target;
    int index;

    public T_Fib( Results r, int i ) 
    {
	results = r;
	target =i;
	index = target-1;
    }

    public void run()
    {
	System.out.println("Starting on: " + target );
	if ( !results.done(index) ) {
	    results.start_work( index );
	    if ( target-1 > 1 && !results.done(index-1) ) {
		T_Fib t1 = new T_Fib( results, target-1);
		t1.start();
		try {
		    t1.join();
		} catch ( InterruptedException e ) {}
	    }
	    if ( index > 1 && !results.done(index-2) ) {
		T_Fib t2 = new T_Fib( results, target-2);
		t2.start();
		try {
		    t2.join();
		} catch ( InterruptedException e ) {}
	    }


	    results.put( results.get(index-1) + results.get(index-2), index );
	    System.out.println( "Done with: " + target + " value: " + results.get(index) );
	}
    }
}

public class Thread_Fib
{
    public static void main( String []args )
    {
	if ( args.length != 1 ) {
	    System.out.print("Usage\njava Fib <index to print> \n");
	    System.exit(0);
	}

	int i = Integer.parseInt(args[0]);
	Results R1 = new Results(i);
	T_Fib tf= new T_Fib(R1, i);
	tf.start();
    }

}






