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.
Related
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.
I realized that this code:
public class TestThread3 extends Thread {
private int i;
public void run() {
i++;
}
public static void main(String[] args) {
TestThread3 a = new TestThread3();
a.run();
System.out.println(a.i);
a.start();
System.out.println(a.i);
}
}
results in 1 1 printed ... and i don't get it. I haven´t found information about how to explain this. Thanks.
results in 1 1 printed
So the first a.run(); is called by the main-thread directly by calling the a.run() method. This increments a.i to be 1. The call to a.start(); then is called which actually forks a new thread. However, this takes time to do so the i++; operation most likely has not started before the System.out.println(...) call is made so a.i is still only 1. Even if the i++ has completed in the a thread before the println is run, there is nothing that causes the a.i field to be synchronized between the a thread and the main-thread.
If you want to wait for the spawned thread to finish then you need to do a a.join(); call before the call to println. The join() method ensures that memory updates done in the a thread are visible to the thread calling join. Then the i++ update will be seen by the main-thread. You could also use an AtomicInteger instead of a int which wraps a volatile int and provides memory synchronization. However, without the join() there is still a race condition between the a thread doing the increment and the println.
// this provides memory synchronization with the internal volatile int
private AtomicInteger i;
...
public void run() {
i.incrementAndGet();
}
...
a.start();
// still a race condition here so probably need the join to wait for a to finish
a.join();
System.out.println(a.i.get());
This behavior can change at any point of time because when a.start() is called, the thread is scheduled for process, not necessary the OS will let it start executing on CPU.
Once a.start() returns, you actually have two threads (one is for main and another is a new thread), and the main would still be running.
The expected result could only come if following happens,
Time
T1 main method calls a.start()
T2 jvm / os schedules thread for execution
T3 a.start() returns and main thread gets context-switched and suspended for other threads.
T4 Spawned thread gets execution context, and its run method is called, which increments value
T5 context switch happens and main thread gets the control back
T6 main thread would print 2
Jatan
You have two main issues here to clear up. I also recommend you examine Gray's answer for more technical information.
**Note: This just skims the surface, but most of the other answers take for granted the background knowledge on these Computer Science topics that I believe you have not yet mastered.
First, threads are not guaranteed order of execution. In general, you should only use threads if they can work asynchronously (independently timed). For this example, you have a timing-specific expected outcome, so threading should probably just be avoided.
This, however, isn't your only issue.
As is, your code also has what is called a Race Condition. A Race Condition occurs when two different threads (or processes) have access to read/manipulate the same data -- In your case, reading i and incrementing via i++.
For example,
Imagine that you and a friend both have a dollar. The Ice Cream Man drives along and stops in front of you. The Ice Cream Man only has one ice cream cone left. There are a couple of ways this could play out:
You are faster than your friend and buy the cone first.
You are slower than your friend and he buys the cone first.
You decide to split the ice cream cone and both pay $0.50.
You two fight and someone else gets to buy the last ice cream cone while you two are distracted.
To mirror this back to the computer,
The main thread where you are printing continues to run even after you started the second thread. (Threads are linked to the same process, so when main returns, the other threads "die". It is possible the thread, even though it a.start()'ed, doesn't finish or may not even get a chance to run at all!)
The other thread gets to run and completes before returning to the main thread.
You take turns executing and everyone gets to do a few lines of code. The out come is really asynchronous here. And this can very likely happen.
The java application process loses the CPU and someone else gets to run (potentially accessing similar shared information.)
TL;DR -
If you want to ensure execution order, then just DO NOT use threads.
There are some cases where syncing up at certain points along the way would be nice. For these cases, you can join the threads (wait for one to finish before continuing), or lock the Race Condition with a Mutex or Semaphore (more advanced synchronization techniques).
I recommend doing some reading on these topics before attempting to jump into battle with the monstrous operating system.
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?
I saw the following example on the internet:
public class TwoThreads {
public static class Thread1 extends Thread {
public void run() {
System.out.println("A");
System.out.println("B");
}
}
public static class Thread2 extends Thread {
public void run() {
System.out.println("1");
System.out.println("2");
}
}
public static void main(String[] args) {
new Thread1().start();
new Thread2().start();
}
}
My question is :
It is guarantee that "A" will be printed Before "B" and "1" will be printed before "2", but is it possible that "1" will be printed twice successively by another thread?.In this piece of code we have at least 3 threads(1 main and 2 created). can we imagine the scheduler runs 1 thread: new Thread1().start(); then gave up immediately after System.out.println("1"); then again run another threat in Thread1().start(); that prints "1" again ?
I am using NetBeans IDE, it seems running such a program always lead to the same first result, so it seems there something with caching. From my understanding you deal with that with declaring volatile variables, can it be done here,how ? if not then what is the solution for caching ?
In today's Computer's processor, we mostly have 2 processors,and still we find many multi-threading programs on the net uses more than 2 threads! isn't this process becomes heavy and slow regarding compiling ?
1) There is no guarantee in what order the threads will proceed.
2) The order is not randomized, either, though. So if you run the program under identical (or very similar) conditions, it will probably yield the same thread interleaving. If you need to have a certain behaviour (including randomized behaviour) you need to synchronized things yourself.
3) A CPU with two cores can only run two threads at the same time, but most threads spend most of their time not actually using the CPU, but waiting for something like I/O or user interaction. So you can gain a lot from having more than two threads (only two can concurrently compute, but hundreds can concurrently wait). Take a look at node.js, a recently popular alternative to multi-threaded programming that achieves great throughput for concurrent requests while having only a single thread of execution.
Answer to your 1/2 question:
Though threads run parallel code inside run method of thread is always executed sequentially.
Answer to your 3 question you can best tune your. Application if number of processors = number of threads but this is not a complete truth since if thread is waiting for some blocking operation then it will lead to un optimized performance since during that time another thread could run.
No. You are not synchronizing your threads in any way, so the exact execution order will be at the mercy of the scheduler. Given how your threads are implemented, I don't see how you could ever having "1" (or "A") being printed twice by a single thread.
What caching? And what variables? Your example code has no variables, and therefore nothing that would be appropriate to use with the volatile keyword. It's quite likely that on a given machine running this program will always produce the same result. As noted in #1, you're at the mercy of the scheduler. If the scheduler always behaves the same way, you'll always get the same result. Caching has nothing to do with it.
That depends upon what the threads are doing. If every thread has enough work to load one CPU core to 100%, then yes, having more threads than you have CPU cores is pointless. However, this is very rarely the case. Many threads will spend most of their time sleeping, or waiting for I/O to complete, or otherwise doing things that are not demanding enough to fully load a CPU core. In such a case there's no problem whatsoever with having more threads that CPU cores. In fact, multithreading predates mainstream multicore CPU's, and even back in the days when none of us had more than one CPU core it was still extremely beneficial to be able to have more than one thread.
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.