package Exam;

class FutureDemo {

	public static void demo() {
		FutureDemo server = new FutureDemo();
		System.out.println("\n\nStarting FutureDemo.demo()");
		for (int n=12;n<=15;n++) {
			startDemoThreads(server, n);
		}
	}

	protected static void startDemoThreads
		(final FutureDemo server, final int n) {
		System.out.println("CALLING service("+n+")");
		Future f = server.service(n);
		System.out.println("GOT future("+n+")");
		startClient(f, n);
		startClient(f, n);
	}
	
	protected static void startClient(final Future f, final int n) {
		new Thread() {
			public void run() {
				int val = ((Integer) f.value()).intValue();
				System.out.println("GOT service("+n+") = " + val);
			}
		}.start();
	}

	public Future service (final int n) {		// unsynchronized
		final Future f = new Future();
		new Thread() {
			public void run() {
				Object result = computeResult(n);
				f.set(result);
			}
		}.start();
		return f;				// immediately return Future
	}

	protected synchronized Object computeResult(int n) {
		randomSleep();
		return new Integer(fibonacci(n));
	}
	
	/**
	* slow, naive algorithm
	*/
	public static int fibonacci(int n) {
		if (n<2) return 1;
		else return fibonacci(n-1) + fibonacci(n-2);
	}
	
	protected void randomSleep() {
		try {
			Thread.sleep((int)(Math.random() * 1000));
			// Thread.sleep((int)(5000));
		} catch (InterruptedException e) { }
	}
}
