when does the main thread die? - java

The question was to generate random numbers between 1 and 99 using a thread. However the problem here is I don't know where does the "main thread is stopping" coming from?
Doesn't the main thread die in the end?
This is the sample output:
Main thread stopping
Random no = 57
Random no = 47
Random no = 96
Random no = 25
Random no = 74
Random no = 15
Random no = 46
Random no = 90
Random no = 52
Random no = 97
Thread that generates random nos is stopping
Mythread class:
public class MyThread extends Thread {
MyThread() {
// default constructor
}
MyThread(String threadName) {
super(threadName); // Initialize thread.
start();
}
public void run() {
// System.out.println(Thread.currentThread().getName());
Random rand = new Random();
int newValue;
for (int i = 0; i < 10; i++) {
newValue = rand.nextInt(99);// generates any vale between 1 to 99
System.out.println("Random no = " + newValue);
}
System.out.println("Thread that generates random nos is stopping");
}
}
Main class:
public class HW5ex2a {
public static void main(String[] args) throws InterruptedException {
MyThread t = new MyThread();
t.start();
t.join();// wait for the thread t to die
System.out.println("Main thread stopping");
}
}

You can't rely on the order that main thread and other threads write to System.out.
Your thread t executes fine, the main thread waits for it to finish and then the main thread exits, all as expected. But this isn't reflected in the order that you see on System.out.
To directly answer your question - the main thread waits for the thread to finish, then it writes a message to System.out, then it dies. The only confusing thing is that, because you are writing to System.out from two different threads, you don't have any guarantees about the relative ordering. Println's from the two different threads could show up interleaved in any way...it just happens to show up with the output from the main thread first.
As Alexis Leclerc points out - you get an unpredictable interleaving, the same as in this java threads tutorial.

Memory Synchronization in a Multi-core System
Since both threads are being run on separate cores (most probably), the objects that the threads have access to are cached by each core (in L1 cache) for improved performance.
Whenever the state of the object is changed, all caches try to synchronize with value in RAM, which is not guarantied to occur immediately.
Some threads might be able to synchronize before other threads even if it violates happens-before relationship between them.
The reason behind this lies in the implementation of the java memory model.
The same thing is happening with System.out object here.
You can not guaranty the order in which the data is passed and flushed through it.
Therefore it is unpredictable. Calling
System.out.flush();
might improve the result, but it will not guaranty.
For more, refer to Multiple threads using System.out.println in Java
Hope this helps.

The main thread exit on below situation :-
Normally when program execution complete .
If you are using System.exit(1).
JVM crashes.
Hope it will help you.

Related

I'm trying to run threads whose run() method has for loop, some loops are being skipped only when sleep() is used.Can anybody please explain why?

I'm trying to run four threads. run() method has a for loop that loops 10 times.In each loop the shared resource "x" is increment by 1. When all threads die, the for loop should have run 4x10 =40 times and x value should equal 40.
That is not happening in all runs of the my code.Each time I run the code it prints a different value of x.Most of the output values of x range from 33 to 40.
Why is it not 40 in every run? Does that mean some for loop loops are being skipped? Is it caused due being blocked?
NOTE : this does not happen when sleep() is removed. It prints 40 every single time.
My code :
public class MyThreadImplementsRunnable implements Runnable{
int x =0;
public void run() {
for(int i=0;i<10;i++){
x = x+1;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
System.out.println("exception");
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyThreadImplementsRunnable m = new MyThreadImplementsRunnable();
Thread t1 = new Thread(m,"first");
Thread t2= new Thread(m,"second");
Thread t3= new Thread(m,"third");
Thread t4= new Thread(m,"fourth");
t1.start();
t2.start();
t3.start();
t4.start();
//To make sure not to go the next statement unless all threads die
while(t1.isAlive()|| t2.isAlive()|| t3.isAlive()||t4.isAlive()){
}
//After all threads die
System.out.println("now all threads are dead");
//value of the shared resource x after all threads exit
System.out.println(m.x);
}
}
Some test runs gave the following results :
Output:
now all threads are dead
34
Output:
now all threads are dead
33
x = x + 1 loads the value of x from memory, adds 1 to it and then stores it in x. Lets say Thread t1 loads 30 and at the same time thread t2 loads 30 they both increment 30 by 1 and store 31 in x instead of 32.
Why it's always 40 without sleep can be caused by many things I hypothesize that it's caused by each of the threads running very quickly and finishing before the next one starts.
You also don't use volatile and there are visibility issues but for now lets not get into that. This is also something you need to learn if you want to write multi-threaded code.
You are using a shared resource(x) between threads which is bound to create many problems like data race, visibility.. Your answer will be always different
#oleg I don't think Volatile will help in this scenario

Two threads referring one variable

I am running the below class .
public class RunThreads implements Runnable {
static int i;
public static void main(String[] args) {
RunThreads job = new RunThreads();
Thread alpha = new Thread(job);
Thread beta = new Thread(job);
alpha.setName("Alpha");
beta.setName("beta");
alpha.start();
beta.start();
}
public void run(){
for(;i<10;i++){
System.out.println(Thread.currentThread().getName() + i);
}
}
}
And my output is :
beta0
beta1
Alpha0
beta2
beta4
beta5
beta6
Alpha3
Alpha8
beta7
Alpha9
I understand I will get different outputs every time I execute it. My question is, why does the output have the value of i as 0 twice, for both the alpha and beta threads i.e. Alpha0 and beta0.
The value of i has been incremented to 1 by the beta thread. So, how does the alpha thread print out Alpha0
I maybe missing something very obvious here. Thanks !
Things are scary when you access shared data with no synchronization etc:
There's no guarantee that the Alpha thread reading i will see the "latest" update from the beta thread or vice versa
It's possible for both threads to start i++ at roughly the same time... and as i++ is basically:
int tmp = i;
tmp++;
i = tmp;
you can easily "lose" increments
If you want to make this thread-safe, you should use AtomicInteger instead:
import java.util.concurrent.atomic.AtomicInteger;
public class RunThreads implements Runnable {
static AtomicInteger counter = new AtomicInteger();
public static void main(String[] args) {
RunThreads job = new RunThreads();
Thread alpha = new Thread(job);
Thread beta = new Thread(job);
alpha.setName("Alpha");
beta.setName("beta");
alpha.start();
beta.start();
}
public void run(){
int local;
while ((local = counter.getAndIncrement()) < 10) {
System.out.println(Thread.currentThread().getName() + local);
}
}
}
Your output may still appear to be in the wrong order (because the alpha thread may "start" writing "Alpha0" while the beta thread "starts" writing "beta1" but the beta thread gets the lock on console output first), but you'll only see each count once. Note that you have to use the result of getAndIncrement() for both the checking and the printing - if you called counter.get() in the body of the loop, you could still see duplicates due to the interleaving of operations.
The simple answer here would be that whether or not the variable is volatile or atomic or whatever, both your threads start out when the variable value is 0, and only change it after the print.
This means that both threads can reach the "print" line before either of them reached the i++.
Which means that both are very likely to print 0, unless one of them is delayed long enough for the other one to update the variable (at which point the question of memory model and data visibility arise).
"While" thread A is doing its update, thread B is reading that value.
Like in:
A: prints i (current value 0)
B: prints i (current value 0)
A: stores 1 to i
You can't assume that those two actions:
for(;i<10;i++){ // increasing the loop counter
and
System.out.println(Thread.currentThread().getName() + i);
printing the loop counter happen in "one shot". To the contrary.
Both threads execute the corresponding instructions in parallel; and there are absolutely no guarantees on the outcome of that.
Threads might run on separate cores in multicore architecture and each core has it's own registry set or local cache, as long as you don't invalidate a cache the running core might not reach to a RAM memory to get up-to-date value and will use the cached one. To make it work as you expected it the variable would have to be marked as volatile, which would invalidate a cache on each write to this memory location and fetch the value directly from RAM.
Update:
As was pointed in comments - volatile is not enough to keep the value up to date, there is a read and write operation on i++. To make it work AtomicInteger would be enough, or slightly more expensive locking around i++.

Multithreading start method

and this a normal thread program
class Counter implements Runnable {
private int currentValue;
public Counter() { currentValue = 0; }
public int getValue() { return currentValue; }
public void run() { // (1) Thread entry point
try {
while (currentValue < 5) {
System.out.println(Thread.currentThread().getName() + ": " + (currentValue++)); // (2) Print thread name.
Thread.sleep(250); // (3) Current thread sleeps.
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " interrupted.");
}
System.out.println("Exit from thread: " + Thread.currentThread().getName());
}
}
//_______________________________________________________________________________
public class Client {
public static void main(String[] args) {
Counter counterA = new Counter(); // (4) Create a counter.
Thread worker = new Thread(counterA, "Counter A");// (5) Create a new thread.
System.out.println(worker);
worker.start(); // (6) Start the thread.
try {
int val;
do {
val = counterA.getValue(); // (7) Access the counter value.
System.out.println("Counter value read by " + Thread.currentThread().getName()+ ": " + val); // (8) Print thread name.
Thread.sleep(1000); // (9) Current thread sleeps.
} while (val < 5);
} catch (InterruptedException e) {
System.out.println("The main thread is interrupted.");
}
System.out.println("Exit from main() method.");
}
}
and the output is
Thread[Counter A,5,main]
Counter value read by main thread: 0
Counter A: 0
Counter A: 1
Counter A: 2
Counter A: 3
Counter value read by main thread: 4
Counter A: 4
Exit from thread: Counter A
Counter value read by main thread: 5
Exit from main() method.
My question is even though the worker thread was started initially before the Main thread enters it's try block, Main thread execution starts first and then when the Main thread goes to sleep child thread gets into action.
As this picture(taken from "A Programmer's Guide To Java SCJP Certification : A Comprehensive Primer 3rd Edition"
Author: Khalid A Mughal, Rolf W Rasmussen) depicts that when the start method is called on the thread it returns immediately.
Please explain this point that why on invoking start method it return immediately and does the thread get starts on calling the start method. As here on calling the start method it doesn't invoke run method of the class. So when does actually the thread starts ?
Also explain this " the call to the start() method is asynchronous."
there are three things that you are missing in your overall analysis.
Call to thread's start method is sequential not parallel. Its the call to run method of Thread that is concurrent. So if you have 5 statements in main method that call start, the 5ht is not going t be called first. Thats the 'happens before' guarantee that JVM specs give you. However the run method of 1 first may get called before or after the call to the second start statement. This depends as its more of a CPU time slicing issue rather than program execution.
When more than 1 thread runs in your program the order of output is in-deterministic. That's because they run in parallel. You can never be sure that the same program will run in same order on two machines or even in two runs on the same machine. In your question you have posted only 1 output. Run the program like 20 times one after another and match the output. I am sure 2 or 3 would be entirely different.
Finally, you are basing your analysis on the order or execution of your concurrent code. That's the biggest blooper programmer make. Concurrent programs are never intended to run in a specific order or sequence. Just try to make your Runnable work an atomic mutually exclusive task (mutually exclusive to the rest of program or even to other Runnables) and track its own execution. Dont mix Threads together.
You cannot directly enforce which Thread is executed/running when. Once you start it, it's handled on lower level(usually by OS) and the results may differ on different machine or even in different execution. If you need more control, you need to use some synchronization mechanism.
The thread is isn't started synchronously underneath the call to start(). It happens later (asynchronously). In other words, just because you called start() doesn't mean the thread has started.
They why and how are all implementation details, that may depend on JVM and/or OS implementations.

Java Thread Programming example - programs is behaving unexpectedly

I am reading Java Thread Programming a book by Paul Hyde.I am into intial chapter. I am running various sample programs in Eclipse IDE.
public class TwoThreadAlive extends Thread {
public void run() {
for (int i = 0; i < 10; i++) {
printMsg();
}
}
public void printMsg() {
// get a reference to the thread running this
Thread t = Thread.currentThread();
String name = t.getName();
System.out.println("name=" + name);
}
public static void main(String[] args) {
TwoThreadAlive tt = new TwoThreadAlive();
tt.setName("my worker thread");
System.out.println("before start(), tt.isAlive()=" + tt.isAlive());
tt.start();
System.out.println("just after start(),tt.isAlive()=" + tt.isAlive());
for (int i = 0; i < 10; i++) {
tt.printMsg();
}
System.out
.println("at the end of main(), tt.isAlive()=" + tt.isAlive());
}}
This program is giving SAME output every time I run it.But it has mentioned that output will differ as JVM will be busy in context switching.Can you please tell me that why it is giving same output?
And it is giving
at the end of main(), tt.isAlive()=true
This should have been
at the end of main(), tt.isAlive()=false
Please help me , this is making me mad.
Nope, the output is correct because by the time the main method executes the last println there is no guarantee that also your thread has finished executing. Add a tt.join(); right before the last print:
tt.join();
System.out
.println("at the end of main(), tt.isAlive()=" + tt.isAlive());
Now the main thread will be blocked until tt finishes, and so the println will execute only after tt is dead.
As for your output being always the same, 10 is a too fine grain value and most likely each thread finishes printing everything by the time it gets context switched. Try with a much larger value.
Not really clean readable code, I think the printMsg() should be static and maybe be placed inside the main class. That way you'll be able to notice that its behavior is not dependent on the custom thread class. Since it prints the current thread name, you could see (for a higher number of iterations) the JVM switching between your TwoThreadAlive thread and the main thread.
About the isAlive question, the TwoThreadAlive thread may not have finished its execution when the main finishes. Change the main thread iterations to 100 and the custom thread to 10000 to see this effect.

Can this Java program ever print a value other than zero?

I have a favorite C# program similar to the one below that shows that if two threads share the same memory address for counting (one thread incrementing n times, one thread decrementing n times) you can get a final result other than zero. As long as n is reasonably large, it's pretty easy to get C# to display some non-zero value between [-n, n]. However, I can't get Java to produce a non-zero result even when increasing the number of threads to 1000 (500 up, 500 down). Is there some memory model or specification difference wrt C# I'm not aware of that guarantees this program will always yield 0 despite the scheduling or number of cores that I am not aware of? Would we agree that this program could produce a non-zero value even if we can not prove that experimentally?
(Not:, I found this exact question over here, but when I run that topic's code I also get zero.)
public class Counter
{
private int _counter = 0;
Counter() throws Exception
{
final int limit = Integer.MAX_VALUE;
Thread add = new Thread()
{
public void run()
{
for(int i = 0; i<limit; i++)
{
_counter++;
}
}
};
Thread sub = new Thread()
{
public void run()
{
for(int i = 0; i<limit; i++)
{
_counter--;
}
}
};
add.run();
sub.run();
add.join();
sub.join();
System.out.println(_counter);
}
public static void main(String[] args) throws Exception
{
new Counter();
}
}
The code you've given only runs on a single thread, so will always give a result of 0. If you actually start two threads, you can indeed get a non-zero result:
// Don't call run(), which is a synchronous call, which doesn't start any threads
// Call start(), which starts a new thread and calls run() *in that thread*.
add.start();
sub.start();
On my box in a test run that gave -2146200243.
Assuming you really meant start, not run.
On most common platforms it will very likely produce non zero, because ++/-- are not atomic operations in case of multiple cores. On single core/single CPU you will most likely get 0 because ++/-- are atomic if compiled to one instruction (add/inc) but that part depends on JVM.
Check result here: http://ideone.com/IzTT2
The problem with your program is that you are not creating an OS thread, so your program is essentially single threaded. In Java you must call Thread.start() to create a new OS thread, not Thread.run(). This has to do with a regrettable mistake made in the initial Java API. That mistake is that the designer made Thread implement Runnable.
add.start();
sub.start();
add.join();
sub.join();

Categories

Resources