I have the following code which uses a single-threaded executor service, but running it uses all the 4 cores on my machine (each core around 80% usage in average).
The question is why is this happening?
And I am not interested here in finding Fibonacci really!
public class MainSimpler {
static int N=35;
static AtomicInteger result = new AtomicInteger(0), pendingTasks = new AtomicInteger(1);
static ExecutorService executor;
public static void main(String[] args) {
executor = Executors.newSingleThreadExecutor();
long before = System.currentTimeMillis();
System.out.println("Fibonacci "+N+" is ... ");
executor.submit(new FibSimpler(N));
waitToFinish();
System.out.println(result.get());
long after = System.currentTimeMillis();
System.out.println("Duration: " + (after - before) + " milliseconds\n");
}
private static void waitToFinish() {
while (0 < pendingTasks.get()){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
}
class FibSimpler implements Runnable {
int N;
FibSimpler (int n) { N=n; }
@Override
public void run() {
compute();
MainSimpler.pendingTasks.decrementAndGet();
}
void compute() {
int n = N;
if (n <= 1) {
MainSimpler.result.addAndGet(n);
return;
}
MainSimpler.executor.submit(new FibSimpler(n-1));
MainSimpler.pendingTasks.incrementAndGet();
N = n-2;
compute(); // similar to the F/J counterpart
}
}
This is related to another question of mine.
Just tried on my machine and I get 35% total CPU usage (4 cores). Note that you have at least 2 threads in your program (the main thread and the executor thread).
However, if I increase
Nto 100, the CPU usage goes up to 90+% because a lot of time is spent in Full GCs (and I was running with 2GB of heap).So it looks like your single thread gets too busy and tasks start accumulating, waiting for being executed.
You could try to run the code with the following JVM parameters:
-XX:+PrintGCThe output on my machine looks like: