Java multi-threading execution on CPU core - java

Context
Let's say I have a simple Java multi threading program with
class Runner1 implements Runnable {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner1: " + i);
}
}
}
class Runner2 implements Runnable {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner2: " + i);
}
}
}
public class App {
public static void main(String[] args) {
Thread t1 = new Thread(new Runner1());
Thread t2 = new Thread(new Runner2());
t1.start();
t2.start();
}
}
The program is running on a multiple core laptop e.g. 4 cores. My understanding from related post is that multithreading can be executed on a single core.
Question
I was wondering about the behavior of the JAVA 2 threads execution on the cpu.
Will the 2 threads be executed by a single cpu core or will they be allocated to different cpu core for execution? Is there a mechanism or default scenario to decide the allocation?
Thanks!

Each thread has an execution stack that tracks its state. It does not matter whether the two threads run on the same CPU or different CPU. In fact what usually happens is that a thread runs a little bit at a time, and the same CPU can be switch back and forth, running one thread for a while, and running the other for a while.
When the threads are allocated to different CPUs, then the possibility of conflicting updates to shared objects is greater, because the threads could be running at the same time causing fine-grained interweaving of updates to memory. If you design your threads to protect against concurrency problems, then it really does not matter much whether they run on the same CPU or different CPU. It does not matter if the thread is run sometimes on one CPU, and later by a different CPU. The thread holds all its own state and does not matter which CPU runs it.
It seems that Java delegates to the operating system the decision on where to run a particular thread.

It can be run on a single-core, but care must be taken when one thread is doing read and the other one does write operation. Internal workings are taken care of by the OS (scheduler).

There is not much to add to the answer of AgilePro.
If you want to control which CPU runs which threads, you need to pin down the thread to a CPU. You could use Thread Affinity library of Peter Lawrey when using Java.
On Linux, every thread has a bitmap with a single bit per CPU the thread is allowed to run on. By default, all bits are set, meaning the thread can run on any CPU. And thread can even migrate from one CPU to another. But using certain system calls, one can pin down a thread to a subset (even a single) of CPUs.

Related

thread parallel to other process java

i have periodic thread that runs every one second and refers the application. the problem is when the thread is running cpu usage goes up and program respond very bad it seems CPU fan is working with full power. maybe there is a problem with using a infinite while here. is there any other way for doing it?
Runnable r1 = new Runnable() {
public void run() {
try {
while (connect.isDisable()){
refresher(rx);
Thread.sleep(1000L);
}
} catch (InterruptedException iex) {}
}
};
Thread thr1 = new Thread(r1);
thr1.start();
if there an alternate way that thhis sets of functions run every one secounds parallel to other process and event handlers respond just like normal?
To begin with, thread is a sequence of execution of statements or code in a program and is nothing hardware. It is a flow of execution which takes place.
A thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system.
And yes, multiple threads may run at the same time if your CPU has more than one core. This will of course increase the CPU usage because multiple processes or sequence of codes are running at the same time. You are asking the CPU to perform 2 or more things at the same time and therefore, over usage is an obvious consequence.
About the fan, may be designed to run faster when CPU usage is higher so that the excess heat generated is driven out efficiently.

Thread swaps in and out automatically without any yield or sleep

I thought a thread only gives up its domination(control?) when we wrote something like yield, sleep inside the run method. The output of the following code I am expected to see is something like :
#1(5), #1(4), #1(3), #1(2), #1(1), #2(5), #2(4), #2(3), #2(2), #2(1), #3(5), #3(4), #3(3), #3(2), #3(1), #4(5), #4(4), #4(3), #4(2), #4(1), #5(5), #5(4), #5(3), #5(2), #5(1)
however, it turns out like all the thread are running at the same time.
the output:
#4(5), #2(5), #1(5), #1(4), #1(3), #1(2), #1(1), #3(5), #5(5), #3(4), #2(4), #2(
3), #4(4), #2(2), #3(3), #3(2), #5(4), #3(1), #2(1), #4(3), #4(2), #4(1), #5(3),
#5(2), #5(1)
I am so confused.
public class SimpleThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public SimpleThread() {
// Store the thread name:
super(Integer.toString(++threadCount));
start();
}
public String toString() {
return "#" + getName() + "(" + countDown + "), ";
}
public void run() {
while(true) {
System.out.print(this);
if(--countDown == 0)
return;
}
}
public static void main(String[] args) {
for(int i = 0; i < 5; i++)
new SimpleThread();
}
}
I thought a thread only gives up its domination(control?) when we wrote something like yield, sleep inside the run method.
Nope, not at all. Threads run in parallel, each executing concurrently with all other threads. It is common to get garbled output when you print to System.out from several threads at the same time.
It hasn't been necessary for threads or processes to explicitly yield control since the Windows 3.x days when the operating system used cooperative multitasking. UNIX operating systems use preemptive multitasking, as does every version of Windows since Windows 95. Preemptive multitasking means the operating system can suspend a thread at any point, for example when it's used up its time slice.
Having threads run in parallel is what enables programs to take advantage of the multi-core architectures that are common today. If only one thread could run at a time there'd be no benefit to having more than one CPU.
According to the specification thread execution order is not guaranteed. Thus you cannot expect that started thread will be finished before second starts.
According to Kathy Sierra oca/ocp java se 7 book (OCA/OCP Java SE 7 Programmer I & II Study Guide):
The thread scheduler is the part of the JVM (although most JVMs map Java threads
directly to native threads on the underlying OS) that decides which thread should
run at any given moment, and also takes threads out of the run state. Assuming a
single processor machine, only one thread can actually run at a time. Only one stack
can ever be executing at one time. And it's the thread scheduler that decides which
thread—of all that are eligible—will actually run. When we say eligible, we really
mean in the runnable state.
Any thread in the runnable state can be chosen by the scheduler to be the one and
only running thread. If a thread is not in a runnable state, then it cannot be chosen to be
the currently running thread. And just so we're clear about how little is guaranteed here:
The order in which runnable threads are chosen to run is not guaranteed.
Although queue behavior is typical, it isn't guaranteed. Queue behavior means
that when a thread has finished with its "turn," it moves to the end of the line of the
runnable pool and waits until it eventually gets to the front of the line, where it can
be chosen again. In fact, we call it a runnable pool, rather than a runnable queue, to
help reinforce the fact that threads aren't all lined up in some guaranteed order
How your threads are scheduled to run largely depend on the underlying OS and hardware. The OS decides when your threads get to execute and in what order.
For example, if you have multiple cores on your machine, the OS will likely try to run your threads concurrently (at the same time).
Even if you only have one core the OS will most likely try to be fair and give all your threads some time to execute since they have the same priority.

ConditionVariable prevents both threads from running simultaneously

I am trying to enforce synchronization between a pair of Android threads for game programming purposes. I have assigned a game thread, which handles most duties, and a render thread, which is tasked with swapping buffers and rendering. When I first asked about thread synchronization, I was referred to the ConditionVariable object as a useful tool to force threads to block until concurrent tasks are completed.
My source code looks like this:
...
final ConditionVariable bufferLock = new ConditionVariable();
final ConditionVariable cycleLock = new ConditionVariable();
bufferLock.open();
cycleLock.open();
Runnable bufferSwapTask = new Runnable()
{
public void run()
{
swapBuffers();
bufferLock.open();
}
};
Runnable renderTask = new Runnable()
{
public void run()
{
Log.d(TAG, "drawAll");
drawAll();
cycleLock.open();
}
};
while(!halt)
{
if(!init)
{
synchronized (userInputLock)
{
fetchUserInput();
}
processUserInput();
gameLogic();
bufferLock.block();
cycleLock.close();
renderThreadHandler.post(renderTask);
recycleDisplayObjects();
enqueueDisplayTree();
cycleLock.block();
bufferLock.close();
renderThreadHandler.post(bufferSwapTask);
}
}
...
So things executed in the right order, but not with the level of performance I had expected. And, when I activated DDMS method tracing, I found that the DVM would actually interrupt and block each thread to allow the other thread to resume, switching back and forth in a manner that strongly suggests that both threads are only being processed by one CPU.
I have had nice simultaneous processing results using ReentrantLocks, so why does ConditionVariable have this effect?
The Linux kernel on Android tries to avoid moving threads between cores. If a thread is "runnable" (i.e. could run but is waiting on another thread) for a while, the kernel can decide to migrate it to another core.
If, in the previous implementation, one of your threads tended to run continuously, it may have kept the other thread in "runnable" long enough to cause the kernel to migrate it. The new implementation might be moving in smaller steps and fall below the threshold.
FWIW, other people have been puzzled by this, e.g. here and here.

Will a thread in a while loop give CPU time to another thread of same type?

If I have the following dummy code:
public static void main(String[] args) {
TestRunnable test1 = new TestRunnable();
TestRunnable test2 = new TestRunnable();
Thread thread1 = new Thread(test1);
Thread thread2 = new Thread(test2);
thread1.start();
thread2.start();
}
public static class TestRunnable implements Runnable {
#Override
public void run() {
while(true) {
//bla bla
}
}
}
In my current program I have a similar structure i.e. two threads executing the same Run() method. But for some reason only thread 1 is given CPU time i.e. thread 2 never gets a chance to run. Is this because while thread 1 is in its while loop , thread 2 waits?
I'm not exactly sure, if a thread is in a while loop is it "blocking" other threads? I would think so, but not 100% sure so it would be nice to know if anyone could inform me of what actually is happening here.
EDIT
Okay, just tried to make a really simple example again and now both threads are getting CPU time. However this is not the case in my original program. Must be some bug somewhere. Looking into that now. Thanks to everyone for clearing it up, at least I got that knowledge.
There is no guarantee by the JVM that it will halt a busy thread to give other threads some CPU.
It's good practice to call Thread.yield();, or if that doesn't work call Thread.sleep(100);, inside your busy loop to let other threads have some CPU.
At some point a modern operating system will preempt the current context and switch to another thread - however, it will also (being a rather dumb thing overall) turn the CPU into a toaster: this small "busy loop" could be computing a checksum, and it would be a shame to make that run slow!
For this reason, it is often advisable to sleep/yield manually - even sleep(0)1 - which will yield execution of the thread before the OS decides to take control. In practice, for the given empty-loop code, this would result in a change from 99% CPU usage to 0% CPU usage when yielding manually. (Actual figures will vary based on the "work" that is done each loop, etc.)
1The minimum time of yielding a thread/context varies based on OS and configuration which is why it isn't always desirable to yield - but then again Java and "real-time" generally don't go in the same sentence.
The OS is responsible for scheduling the thread. That was changed in couple of years ago. It different between different OS (Windows/Linux etc..) and it depends heavily on the number of CPUs and the code running. If the code does not include some waiting functionality like Thread.yield() or synchhonized block with a wait() method on the monitor, it's likely that the CPU will keep the thread running for a long time.
Having a machine with multiple CPUs will improve your parallelism of your application but it's a bad programming to write a code inside a run() method of a thread that doesn't let other thread to run in a multi-threaded environment.
The actual thread scheduling should be handled by the OS and not Java. This means that each Thread should be given equal running time (although not in a predictable order). In your example, each thread will spin and do nothing while it is active. You can actually see this happening if inside the while loop you do System.out.println(this.toString()). You should see each thread printing itself out while it can.
Why do you think one thread is dominating?

Is fork / join multithreaded?

If I have 2 CPUs and schedule 1000 tasks for the fork / join framework to work on, will the tasks be executed in a maximum of 2 at a time, or will more tasks be executed in parallel on the same CPU? (say, maybe one task is waiting for I/O, in which case the CPU would become idle and another thread could run)
If you do not include any restriction yourself, none will be applied and Java will fork as many threads as it can (maybe all 1000 depending on system restrictions). This is not ideal. If you're doing a computation which is likely to have some IO time but not be IO bound even at large amounts of concurrent processing, you might be able to justify running one more thread then the available number of CPUs. Running all 1000 at once would not be wise.
If I have 2 CPUs and schedule 1000 tasks for the fork / join framework to work on, will the tasks be executed in a maximum of 2 at a time, or will more tasks be executed in parallel on the same CPU?
If you have a dual core CPU, you can only actually execute 2 threads at once.
According to the ForkJoin documentation:
A ForkJoinPool is constructed with a given target parallelism level;
by default, equal to the number of available processors. The pool attempts to maintain enough active (or available) threads by
dynamically adding, suspending, or resuming internal worker threads,
even if some tasks are stalled waiting to join others. However, no
such adjustments are guaranteed in the face of blocked IO or other
unmanaged synchronization.
So it will probably run them two at a time on your 2 CPUs, possibly four at a time if the CPUs are hyperthreaded (I'm not certain). If you aren't happy with the default level of parallelism, you can specify a requested level of parallelism by calling the ForkJoinPool constructor that takes the level of parallelism as a parameter.
Is hyperthreading enabled on the cpu? If so you may run 2+ processes at the same time.
Hyper-threading works by duplicating certain sections of the processor—those that store the architectural state—but not duplicating the main execution resources. This allows a hyper-threading processor to appear as two "logical" processors to the host operating system, allowing the operating system to schedule two threads or processes simultaneously.
Hyper-threading # wikipedia
I made a test to verify this:
import java.util.concurrent.*;
public class Test {
private static class TestAction extends RecursiveAction {
private int i;
public TestAction(int i) {
this.i = i;
}
protected void compute() {
if (i == 0) {
invokeAll(new TestAction(1), new TestAction(2), new TestAction(3),
new TestAction(4), new TestAction(5), new TestAction(6));
return;
}
System.out.println(i + " start");
try { Thread.sleep(2000); } catch (Exception e) { }
System.out.println(i + " end");
}
}
public static void main(String[] args) {
new ForkJoinPool().invoke(new TestAction(0));
}
}
The results of that running with the reference Oracle implementation is:
1 start
6 start <- wait 2 seconds
1 end
2 start
6 end
5 start <- wait 2 seconds
2 end
3 start
5 end
4 start <- wait 2 seconds
4 end
3 end
The same behavior is consistent on both Linux and Mac OS X.
So the answer to the question is: yes, the tasks will be executed on exactly the number of CPUs specified by the parallelism parameter (or the total available CPUs by default). If CPU time becomes available and the tasks simply block waiting for something, then the framework will do nothing automatically to run other tasks.
Since the documentation I've seen so far is pretty vague about what exactly the framework is supposed to do if the CPU is free, this could be an implementation detail.
By default, the Fork/Join Framework tries to maintain the number of threads equal to one less than the number of cores (if a single core machine, then one thread is created). You can see this code in makeCommonPool method in ForkJoinPool class.
If you think that this under-utilises your CPU, you can provide a custom value for parallelism.
But most interestingly, there is a way to make ForkJoinPool create more threads when the current thread occupying the CPU blocks on IO. All you have to is to implement the code block which actually blocks on the IO inside an implementation of the block method of the ForkJoinPool.ManagedBlocker object, and pass that ManagedBlocker object to the managedBlock method of the ForkJoinPool class. When this is done, the ForkJoinPool checks if the current thread calling this method is an instance of a ForkJoinPoolWorkerThread. If it is, the ForkjoinPool compensates by creating new threads which can take over the CPU.
ForkJoinPool fjp = ForkJoinPool.common();
Runnable task = new Runnable(){
public void run(){
//Some cpu-intensive code
ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker(){
public boolean isReleasable(){
//return true if an IO/blocking operation is to be done.
}
public boolean block(){
//Do an IO Operation here
//return true if all blocking code has finished execution.
//return false if more blocking code is yet to execute.
}
});
//Some more CPU intensive code here
}
};
fjp.submit(task);

Categories

Resources