Are new threads automatically assigned to a different CPU Core in Java?
In Java, and more specifically, Android, are new Threads automatically assigned to a different CPU core than the one I am currently utilizing, or should I take care of that?
The decision of what threads run on what cores is handled by the OS itself (in Android, based off of the Linux scheduler). You cannot affect those decisions yourself; the decisions are automatic and dynamic.
does it matter how the new thread is created, using the Thread class or submitting a Runnable to an Executor, that maintans a pool of threads?
With respect to what cores a thread runs on, the OS neither knows nor cares whether an Executor
is involved, or even if the programming language that app was written in has something called Executor
.
In Java, and more specifically, Android, are new Threads automatically assigned to a different CPU core than the one I am currently utilizing, or should I take care of that?
In Java threads are simply separate sequence of executions, but in Android it is a little more complicated than that. Android creates one main thread per application. This main thread is responsible for the UI and other tasks related to events (queue). For doing background work you have to create separate worker threads.
Simple threads are handled by the Android OS automatically, and they may or may not run on separate cores. If you are running 10 threads, it is quite possible that they all run on one core leaving all other cores idle.
If you need to run more than one threads and you want to run each thread on a separate core you should use ThreadPoolExecutor
; it will handle thread creation and map it on number of CPU cores available. You can set various parameters according to your requirement. See what Android is saying:
A ThreadPoolExecutor will automatically adjust the pool size (see getPoolSize()) according to the bounds set by corePoolSize (see getCorePoolSize()) and maximumPoolSize (see getMaximumPoolSize()). When a new task is submitted in method execute(Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.
See ThreadPoolExecutor for detail.
does it matter how the new thread is created, using the Thread class or submitting a Runnable to an Executor, that maintans a pool of threads?
yes, see the answer above.
Update
By saying "to run each thread on a separate core use ThreadPoolExecutor", I meant that ThreadPoolExecutor
can do that if it is used properly in a careful manner.
Java does not map threads directly on the CPU. Java leaves threads schedule (by mapping on to the OS' processes) on OS but how we create threads influence scheduling at OS level. However Java, can assign priority to threads but again it is up to the OS to honor these priorities.
There are various parameters we should consider while creating a thread pool, few are as follows:
i) Threads should be equal in complexity.
ii) Comparing CPU bound tasks with I/O bound, I/O bound task usually need more threads than available core for optimal utilization of CPU
iii) Dependency between threads effect negatively
If threads are created keeping these points in mind, ThreadPoolExecutor
can help achieve a 100% of the CPU utilization, meaning one thread per core (if the thread pool's size is equal to the number of cores and no other thread is running). A benefit of ThreadPoolExecutor
is that it is cost effective as compare to creating threads separately and it also eliminates context switching which wastes a lot of CPU cycles.
Achieving the 100% of the CPU utilization while making things concurrent, is not an easy task.