Thread swaps in and out automatically without any yield or sleep - java

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.

Related

Java multi-threading execution on CPU core

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.

How long does a Java thread own a CPU time slice?

Each Java thread is mapped to a kernel thread in Windows and in Windows the time slice for thread switching is 10-100ms.
However, from the result of the following simple codes, it seems each thread switches the CPU resource every line of code. Why?
class MyThread extends Thread{
public MyThread(String name){
super(name);
}
public void run(){
for(int i=0;i<5;i++){
System.out.println( this.getName()+":"+i);
}
}
public static void main(String args[]){
Thread p = new MyThread("t1");
p.start();
for(int i=0;i<5;i++){
System.out.println( "main:"+i);
}
}
}
First of all, you don't tell us what output you are seeing and what you are expecting to see. So it is not possible to explain the former, or why the latter may be off-base.
However, there are a number of factors that could explain why the output is different to what you expect.
The output is likely to depend on the number of cores (or hyperthreads) on your system. And the number of them that the OS makes available to your Java application.
If there are higher priority threads running in the Java application itself or in other parts of the system, that will perturb time slicing. (A low priority thread's time-slice may be cut short if a high priority thread needs to be scheduled.)
Java thread rescheduling doesn't just occur due to time slicing. It can also happen when a thread does blocking I/O, or when it attempts to acquire a Lock or a mutex, or wait(...) or sleep(...) or something similar.
System.out.println has some hidden synchronization going on behind the scenes so that two threads printing at the same time don't cause corruption of the shared buffer data structures.
In short, whatever output you see from that program, it will not be clear evidence of time slicing behavior. (And my guess is that it is not evidence of any significance at all.)
But the answer to your question:
How long does a Java thread own a CPU time slice?
is that it is not possible to predict, and would be very difficult to measure.
System.out.println is a blocking operation that takes a lot of time compared to everything else you're doing. It's also synchronized so that only one thread can print a line at a time.
This causes the alternating behaviour you're seeing. While one thread is printing, the other one has plenty of time to get ready to print, call println, and wait for the first thread to complete. When the first thread finishes printing, the second one gets to print, and the first one will be back waiting for it to finish before it's done.

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?

Question on Java Thread, output consistent

In the below code the answer is always Started 0 1 2 3 Complete. Im just wondering how it is possible.
If someone could help with the consistency of the output, it would be nice
public class TestOne extends Thread {
/**
* #param args
*/
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
Thread t = new Thread(new TestOne());
t.start();
System.out.println("started");
t.join();
System.out.println("Complete");
}
public void run(){
for(int i=0;i<4;i++){
System.out.println(i);
}
}
Most likely you're getting the same results because, most of the time, the main thread starts a new thread then, before that new thread has a chance to print anything, the main thread prints its started message. The join in the main thread then forces it to wait until the other thread has finished, then it prints Complete.
You have a race condition here. The instant you start the second thread, it's indeterministic as to which order the lines will be output (other than the complete line which is made deterministic by virtue of the wait call, as previously mentioned).
But a race condition doesn't guarantee that you'll get different results on multiple runs, only that it is possible. You still shouldn't rely on that behaviour, of course.
For example, the following code:
public class TestOne extends Thread {
public static void main (String[] args) throws Exception {
Thread t = new Thread (new TestOne());
t.start();
Thread.sleep (1000); // <- Added this.
System.out.println ("Started");
t.join();
System.out.println ("Complete");
}
public void run() {
for (int i = 0; i < 4; i++) {
System.out.println (i);
}
}
}
will output:
0
1
2
3
Started
Complete
Although, even then, the order is not guaranteed as it may take more than a second for the thread to "warm up" - sleep is rarely a good solution to race conditions. I've just used it here for illustrative purposes.
When you say Thread t = new Thread(); nothing special happens because you are not creating a "Thread" per se. It is just an object that has the "characteristics" to become a thread of execution. For the object to be a "Thread" you have to call t.start(); and this is where the magic lies.
When you say t.start() the JVM creates a new stack for the newly created thread to run. It associates that stack to the thread object in question. And then makes it available for scheduling. Basically this means that it queues the thread in the JVM scheduler and in the next time slice it is also available for execution. The JVM actually does a lot more than this, my answer is just oversimplified for your example.
Invariably, meanwhile all these thread + stack creation, your main thread has the opportunity to move to its next instruction which in your case is System.out.println("started");.
Theoretically, what you say is true, "Started" could come anywhere in between 0, 1, 2, 3. However in reality, since your t.start() is an "expensive" method, it takes some time to complete, during which the main thread generally gets the chance to execute its next instruction.
If you want to know the details of t.start(); look into the Java source code.
Clearly, you are seeing a consistent result (and this particular result) because on your machine the call to the child thread's run method is consistently happening after the println in the main thread.
Why is it consistent?
Well, simply because your platform's native thread library is behaving in a consistent fashion!
Typical modern Java virtual machine implementations use the host operating system's native thread support to implement Java threads, and to perform Java thread scheduling. On your machine, the native thread implementation appears to be consistently allowing the current thread to return from the Thread.start() call immediately and keep executing.
However, it is not guaranteed that this will always happen. For instance, if the machine was heavily loaded and the main thread had just about exhausted its current timeslice, it could get descheduled during or immediately after the start call, allowing the new thread to run first.
Furthermore, on another platform the normal scheduler behaviour could be different. The scheduler could consistently cause the current thread to deschedule and let the new one go first. Or it could happen "randomly".
The JVM and Java library specs deliberately do not specify which thread "goes first" precisely to allow for differences in the thread implementation ... and variation due to differences in hardware, system load and so on.
Bottom line - the apparent consistency you are seeing is an "artifact", and you shouldn't rely on it, especially if you want your application to work on a wide range of JVMs.
Simply put, the scheduling of the started thread with respect to the main thread is JVM implementation dependent. But that being said, most implementations, if not all, will leave the starting thread running to the completion of its timeslice, until it blocks on something, or until it is preempted by a higher priority thread (if preemptive scheduling is being used, also JVM implementation dependent).
The Java spec just does not say very much which is very specific about threading, deliberately to grant JVM writers the most scope for their implementation.
t.join() means "block until thread t has finished", which explains the "Completed" being last.
EDIT: In answer to question re "Started"...
The call to Thread.start() means "please schedule this thread to run", and it will start when java feels like starting it. The chance of that happening between t.start() the println() is platform dependant, but small on systems I've used (thx to # Stephen C for platform info).
This code however outputs 0, Started, 1, 2, 3, Completed:
Thread t = new Thread(new TestOne());
t.start();
try
{
Thread.sleep(100); // Added sleep between t.start() and println()
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Started");
t.join();
System.out.println("Complete");
When you start a thread it takes time (nothing comes for free or occurs instantly)
The thread which is already running will almost always be quicker to print out than a thread which has just started.
If you really want to the order to be different every time you can use run() instead of start() This works because you only have one thread.

How does method yield work?

In javadoc there is said that yield method
Causes the currently executing thread object to temporarily pause and allow other threads to execute.
And Katherine Sierra and Bert Bates SCJP book says that
yield() is supposed to do is
make the currently running thread head back to runnable to allow other threads of
the same priority to get their turn.
So what actually method is doing?
Given a multi-threaded application, yield will cause the currently executing thread to pause execution and be set in a waiting state. The JVM will then begin running another thread that was previously in a waiting state.
I believe the same thread that just yielded could technically be scheduled to start again.
And I have yet to see this in the wild though. So I think it is safe to avoid.
To elaborate:
In a multi-threaded environment threads are scheduled and unscheduled off and on at the JVM's will. So, even if yield is not called in code, your thread can/will automatically yield to other threads when the JVM decides it should. This allows multi-threading to work in an environment with only one processing core.
Calling yield simply tells the JVM to put the current thread in a waiting state even if the JVM wasn't going to.
I shall attempt an illustration:
The following is a very simplified illustration of the execution of 2 threads over time (assume 1 core)-
Thread\Time 1 2 3 4 5 6 7 8 9
Thread 1 ----------- ----- -------
Thread 2 ------- ---------- ------
Whenever you see a '-' that means a thread is executing. A ' ' means that the thread is waiting. As you can see, only 1 thread can actually run at a time. So, while 1 runs, the other waits. What yield is intended to do is give other threads a chance to run ahead of the currently running thread.
yield() is generally used when you are waiting on a thread for something to occur but don't want to block the CPC cycles with something like while(condition){ ...} . The way yield() works differ from platform to platform and depends on the Thread Scheduler and you shouldn't rely on it behaving in a particular way.
It originates from the time of cooperative multitasking.
The basic idea is, the processor executes only one thread until:
this thread ends
this thread does some blocking operation, like object.wait() or Thread.sleep, waiting on some IO operation to complete, waiting for some object monitor, or similar.
this thread invokes Thread.yield().
In each of this cases the thread scheduler then selects another thread to execute. So, to be fair to other threads, you would in longer loops without any blocking operations regularly call yield(). (If no other thread is ready to run, then the same thread would be scheduled again, so no really big performance loss.)
In modern VMs thread switching can occur on any point, not only these listed, threads may even be executed simultaneously, so it is not really necessary, and some VMs may ignore it altogether (similar to System.gc().)
yield() method is there to make sure that all same priority threads in a application would not cause starvation. For e.g. five threads are there in a application and all of them are of same priority. Now suppose one thread got chance to run and this thread is taking so long to complete its task and hence other threads wont get chance to run. So to avoid this kind of situations yield() is there to rescue.
Ultimately, the call to yield() results in calling os methods like this, which in principle would put the task itself back in to the run queue and let the next task run (source):
/**
* sys_sched_yield - yield the current processor to other threads.
*
* This function yields the current CPU to other tasks. If there are no
* other threads running on this CPU then this function will return.
*/
SYSCALL_DEFINE0(sched_yield)
{
/*
* lock this runqueue and disable interrupts.
*/
struct rq *rq = this_rq_lock();
schedstat_inc(rq, yld_count);
current->sched_class->yield_task(rq);
/*
* Since we are going to call schedule() anyway, there's
* no need to preempt or enable interrupts:
*/
__release(rq->lock);
spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
_raw_spin_unlock(&rq->lock);
preempt_enable_no_resched();
schedule();
return 0;
}
Threads may be in states ready (runnable), blocked (e.g., waiting for some io to finish), or running; this is common to all thread implementations, although some particular implementations may have more states.
Yield causes the thread to change from running to runnable, and wait for the scheduler to change it to running again, in the future. This is what is meant in the SCJP book.
To the thread, it seems like it has been paused for a while, like described in the javadoc. So both statements are correct, just differently phrased.
Hope it helps!
package yield;
public class ThreadYieldApp {
Thread th1 = new Thread("Thread 1") {
public void run() {
for(int i = 0; i <= 10; i++) {
System.out.println("Before Yield - " + Thread.currentThread().getName() + " at index - " + i);
//Currently pauses the thread and checks for other threads of same priority, and passes control to it based on Thread Scheduler pick
Thread.yield();
System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
Thread th2 = new Thread("Thread 2") {
public void run() {
for(int i = 0; i <= 10; i++) {
System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
public static void main(String[] args) {
ThreadYieldApp threadYieldApp = new ThreadYieldApp();
threadYieldApp.th1.start();
threadYieldApp.th2.start();
}
//Happy coding -- Parthasarathy S
}

Categories

Resources