import java.util.concurrent.atomic.AtomicInteger;

public class Main {

	private static final long MAX_RUN_TIME = 5000l;
	private static final long ESTIMATED_OVERHEAD = 125l;

	public static AtomicInteger totalCalculations = new AtomicInteger(0);

	public static void main(String[] args) throws java.lang.Exception {

		final long startTime = System.currentTimeMillis();
		final int NUM_CPU_CORES = Runtime.getRuntime().availableProcessors();

		System.out.println("Starting on " + NUM_CPU_CORES + " threads.");
		final Thread[] threads = createThreads(NUM_CPU_CORES, new WorkPackage());
		startThreads(threads);

		new Thread(new Runnable() {
			@Override
			public void run(){
				long currentTime = 0;
				long elapsedTime = 0;
				long remainingTime = MAX_RUN_TIME;

				while(elapsedTime < (MAX_RUN_TIME - ESTIMATED_OVERHEAD)) {
					if(remainingTime > ESTIMATED_OVERHEAD) {
						try {
							Thread.sleep(remainingTime - ESTIMATED_OVERHEAD);
						} catch(InterruptedException e) {
							e.printStackTrace();
						}
					}
					currentTime = System.currentTimeMillis();
					elapsedTime = currentTime - startTime;
					remainingTime = MAX_RUN_TIME - elapsedTime;
				}

				stopThreads(threads);
				System.out.println("Completed " + totalCalculations.intValue() + " useless calculations over "
						+ (currentTime-startTime)/1000f + " seconds!");
				System.exit(0);
				Thread.currentThread().interrupt();
			}
		}).start();
	}

	private static Thread[] createThreads(final int numCpuCores, final Runnable runnable) {
		Thread[] workerThreads = new Thread[numCpuCores];
		for(int i=0; i<numCpuCores; i++) {
			workerThreads[i] = new Thread(runnable);
		}
		return workerThreads;
	}

	private static void startThreads(final Thread[] threadsToRun) {
		for(Thread thread : threadsToRun) {
			thread.start();
		}
	}

	private static void stopThreads(final Thread[] threadsToStop) {
		for(Thread thread : threadsToStop) {
			thread.interrupt();
		}
	}
}

class WorkPackage implements Runnable {
	@Override
	public void run() {
		while(!Thread.interrupted()) {
			int result = xorShiftRandom(Integer.MAX_VALUE) + xorShiftRandom(Integer.MAX_VALUE);
			Main.totalCalculations.incrementAndGet();
		}
	}

	private long currentValue = System.currentTimeMillis();
	private int xorShiftRandom(final int max) {
		currentValue ^= (currentValue << 21);
		currentValue ^= (currentValue >>> 35);
		currentValue ^= (currentValue << 4);
		int out = (int) currentValue % max;
		return (out < 0) ? -out : out;
	}
}