Home > front end >  ThreadPoolExecutor CPU 100% load
ThreadPoolExecutor CPU 100% load

Time:01-08

I needed to execute my workers on several cores because I have a possibility to separate my task to several tasks manually, so I limply need to use newFixedThreadPool, but my worker raises a 100% CPU loading. If it using the whole cores for it it's okay, but it's working only 2x faster than without thread pool, so seems that it using it without sense.

I tried to use plain newFixedThreadPool:

ExecutorService pool = Executors.newFixedThreadPool (Runtime.getRuntime ().availableProcessors ());

for (int i = 0; i < Runtime.getRuntime ().availableProcessors (); i  )
    pool.execute (new MyTask (this));
            

and ThreadPoolExecutor with passed queue:

LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<> ();

for (int i = 0; i < Runtime.getRuntime ().availableProcessors (); i  )
    queue.add (new MyTask (this));

ThreadPoolExecutor pool = new ThreadPoolExecutor (Runtime.getRuntime ().availableProcessors (), Runtime.getRuntime ().availableProcessors (), 0, TimeUnit.MILLISECONDS, queue);

pool.prestartAllCoreThreads ();
        

And result still the same.

MyTask is trivial and written for example:

    protected static class MyTask implements Runnable {
        
        @Override
        public void run () {
            
            int i = 0;
            
            while (true)
                i  ;
            
        }
        

After running workers without ThreadPoolExecutor CPU loading is normal and varies for about 10-20%. So what will be wrong?

CodePudding user response:

While it is not clear exactly what you are trying to find out, you have to keep this in mind.

A single thread will only make use of one (virtual) core at a time. It is usually backed by a single OS kernel process (I say usually because there are a lot of fancy stuff some frameworks and VMs are doing with Green Threads and what not lately).

When the thread blocks (to do I/O or wait for something, or sleeps, or there is an explicit call to yield()), it relinquishes the CPU core to another thread.

So running a simple infinite loop on a single worker thread will only make use of 1 core. Which is why you observe 10% to 20% loading (depending on how many virtual cores you have on your machine).

On the other hand, if you create a thread pool of as many cores as you have, all doing the same infinite loop on separate threads, each will take one available core and use it, which will drive your CPU loading to 100%.

They are completely separate workers, so you can't expect your first worker to complete faster or anything of that sort. If anything it will be slower, because you have exhausted all CPU resources, and the OS and even the JVM now will compete to do its own thing, like run the garbage collector etc.

CodePudding user response:

A CPU-bound task is bound to take all of the CPU

You have an infinite loop that does nothing more than run calculations. That code never blocks. That is, the code never stops to wait on externalities. For example, the code never contacts a database, never writes to storage, and never makes a call over the network.

With nothing to do but calculations on the CPU, such a task is considered to be CPU-bound. Such a task will use 100% of a CPU core.

You multiply this task, to have one such task per core for every core in your machine. So all cores are pushed to 100%. Likely your machine will get hot, fans will spin, and CPU will throttle.

This seems rather obvious. Perhaps you should edit your Question to explain why you expected a different behavior.

  • Related