Query about threads in java - java

I was reading Multithreading from The Complete Reference and then I was struck at this code,I am unable to understand the output of this code.Can somebody help me with this?
class NewThread implements Runnable
{
Thread t;
NewThread()
{
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start();
}
public void run()
{
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
}
catch (InterruptedException e)
{
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class First
{
public static void main(String args[])
{
new NewThread();
try
{
for(int i = 5; i > 0; i--)
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
It produces the output:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread
Main Thread: 2
Main Thread: 1
Main thread exiting
From the main() method,the NewThread() constructor is called and then an instance of Thread class is created named "demo thread" and the first print() statement gets executed.After that the start() method is called.Is this start method not supposed to call run() method implicitly and so the child loop should be executed,but according to the output the control goes in the main loop.How can the control go to the main() loop,even if we are calling t.start()?Can somebody please clarify the code output to me please?

Once start() is called, there are now two threads running simultaneously. start() returns immediately and the main loop continues (one loop very 1000mS). But the child loop is now running at the same time also - one loop every 500mS. So, until each loop finishes, there will be two child lines printed for every main line.

Unless there's a happens-before relationship, the order of execution of independent threads is nondeterministic; this is what makes concurrency challenging. After t.start() is called, there's no relationship at all between the main thread and the thread in t, and in the unlikely case where the system is heavily loaded, one thread or the other could theoretically complete all in sequence before control returns to the other thread at all.

Related

How to distinguish threads that have locked to different instances?

I learned that threads can lock onto "the resources", let's say an object, they're using so that only one at a time is allowed to use and modify it which is the problem of synchronization. I created two different instances of one class and fed it to my threads, trying to make sure they're locking on different "resources". How ever they still behave as though they've locked on same resources? I'm confused as I haven't had any experience and knowledge regarding threads.
So this is a code I modified from an online tutorial to try what I was thinking about:
public class TestThread {
public static void main(String args[]) {
PrintDemo PD1 = new PrintDemo("No.1"); //just prints from 1 to 5
PrintDemo PD2 = new PrintDemo("No.2");
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD1 );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD2 );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
threadName = name;
PD = pd;
}
public void run() {
synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
class PrintDemo {
private String name;
PrintDemo(String name) {
this.name = name;
}
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println(name + " Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
It should be different each time I run, but it always the same:
output:
Starting Thread - 1
Starting Thread - 2
No.1 Counter --- 5
No.1 Counter --- 4
No.1 Counter --- 3
No.1 Counter --- 2
No.1 Counter --- 1
Thread Thread - 1 exiting.
No.2 Counter --- 5
No.2 Counter --- 4
No.2 Counter --- 3
No.2 Counter --- 2
No.2 Counter --- 1
Thread Thread - 2 exiting.
edit #1: I put the entire code as you asked. i also tested the code without overriding start. it had the same result.
If you add a
Thread.sleep(1000)
between each tick of your PrintDemo, you will likely see that both threads do 5, then 4, then 3, etc. Right now the first thread is being too fast, it completes faster than the 2nd thread can be started by the main thread.
Synchronization has no effect here, both threads synchronize on different resources, which has no effect. After proving (with the Thread.sleep) that both threads execute at the same time, then add synchronization on a shared object, and both threads will fully execute one after the other, even with the waiting.
The problem is in your ThreadDemo.start() method.
Your ThreadDemo class is declared with extends Thread, but you never actually use it as a thread. Instead, the real thread objects are created inside ThreadDemo.start().
t = new Thread (this, threadName);
t.start ();
Here's what probably is happening:
Main thread calls T1.start(). It creates a new thread, which takes some time, and then it starts the thread.
The new thread starts printing its five lines, while the main thread simultaneously calls T2.start().
The T2.start() call creates another new thread, which takes some time. Meanwhile, the other thread still is printing. It doesn't print very many lines, and system.out is buffered, so chances are, it is able to print all of them before any actual I/O happens. Meanwhile...
...The main thread still is creating that T2 thread. It takes some time.
Finally, the main thread is able to start the T2 thread, which prints its five lines, and...
...end of story. That's how it probably goes down.

Unable to synchronize two threads when Thread class is extended but works when implementing Runnable interface

Here the synchronized block is not working:
class NewThreadt extends Thread {
synchronized void dota(){
for(int i = 5; i > 0; i--)
{
System.out.println(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
}
}
// This is the entry point for the second thread.
public void run() {
dota() ;
System.out.println("Exiting child thread.");
System.out.println(Thread.currentThread()); //gives the name of thread
}
}
class trial {
public static void main(String args[]) {
NewThreadt t=new NewThreadt();
NewThreadt q=new NewThreadt();
t.start();
q.start(); both are in main
System.out.println("Main thread exiting.");
}
}
Output:
Main thread exiting.
5
5
4
4
3
3
2
2
1
1
But when I make the following changes the Synchronized Block works:
class NewThreadt implements Runnable //instead of class NewThreadt extends Thread
NewThreadt abc=new NewThreadt(); //Changes in main()
Thread t=new Thread(abc);
Thread q=new Thread(abc);
t.start();
q.start();
Output:
Main thread exiting.
5
4
3
2
1
5
4
3
2
1
Why is this happening? Aren't both of these examples supposed to work the same?
Synchronization depends on sharing a common lock. The synchronized keyword on an instance method means that for a thread to enter that method it first has to acquire the lock on this.
In your first example there is no shared lock, each of the two threads is locking on itself. Each thread acquires its own lock and nobody blocks, the two threads run concurrently. (The only locking going on here is that when a thread wants to write to the console it has to acquire the console's lock first, so that each println takes place atomically.)
In the second example the same Runnable is passed into each thread, so they both lock on the same object, the Runnable. One thread acquires the lock and executes, the other has to wait for the first thread to release the lock.
If you change the second example to give each thread a separate Runnable:
Thread t=new Thread(new NewThreadt());
Thread q=new Thread(new NewThreadt());
t.start();
q.start();
then you'll see synchronization doesn't work and it behaves like the first example.

Understanding join() method in java () without mentioning calling thread

The following code gives an output of 9; But my question is which thread will call join() method. main thread calls join method than what does it mean? all the other threads should wait till main method completes? Then the output shouldn't be 9?
public class Starter extends Thread {
private int x = 2;
public static void main(String[] args) throws Exception {
new Starter().makeItSo();
}
public Starter(){
x = 5;
start();
}
public void makeItSo() throws Exception {
join();
x = x - 1;
System.out.println(x);
}
public void run() { x *= 2; }
}
That join() in makeItSo() is indeed confusing. Your code is equivalent (ignoring exceptions) to this, with the join() removed from makeItSo(), and removing start() from the Starter constructor:
Starter other_thread = new Starter();
other_thread.start(); // run gets executed in other_thread
other_thread.join(); // waits for other_thread to finish running
other_thread.makeItSo();
As in your code, it is the main thread that calls join on the secondary thread. That causes the main thread to wait for the end of run() before computing x-1 and printing it out.
So the secondary thread will have computed x*2 -> 10, and the main thread computes x - 1 -> 9 after that thanks to the join().
public class Starter extends Thread {
private int x = 2;
public static void main(String[] args) throws Exception {
System.out.println("Start of main "+Thread.currentThread().getName());
new Starter().makeItSo();
System.out.println("End of main "+Thread.currentThread().getName());
}
public Starter(){
x = 5;
System.out.println("Before starting thread " + Thread.currentThread().getName());
start();
System.out.println("After starting thread " + Thread.currentThread().getName());
}
public void makeItSo() throws Exception {
System.out.println("Before join " + Thread.currentThread().getName());
join();
System.out.println("After join " + Thread.currentThread().getName());
x = x - 1;
System.out.println(x);
System.out.println(Thread.currentThread().getName());
}
public void run() {
System.out.println("Inside running thread "+Thread.currentThread().getName() +"with value of x:" +x);
x *= 2;
}
}
OUTPUT
Start of main main
Before starting thread main
After starting thread main
Before join main
Inside running thread Thread-0with value of x:5
After join main
9
main
End of main main
Go through the code and it is pretty much self explanatory. The main thread is the one which waits at join for thread-0 spawned at the constructor to get completed. The main thread doesnt end untill the makeItSo() function call ends.
The main thread calls the join method, so it will wait for the thread spawned by Starter to stop. When you invode new Starter() it starts a thread, that finishes quickly. It's possible make is so will wait a bit until starter finishes. For a better test put a sleep in run and track the elapsed time. You will see that it wait for Starter to end.

java multithreading - child thread does not start immediately

I am learning about MULTITHREADING in java and I want to know why in the following code, the child thread does not immediately run when the start method is executed to invoke the run method in the child thread?
Instead, after executing the start method, the main thread keeps executing its code and starts printing ".". Which it does three times and the control is taken over by the child thread. The child thread then executes its code one time and returns back to the main thread. Then main thread completes and then the child thread completes its execution as well.
I am unable to understand why this happens?
class MyThread implements Runnable {
String thrdName;
MyThread(String name) {
thrdName = name;
}
public void run() {
System.out.println(thrdName + " starting.");
for (int count = 0; count < 10; count++) {
System.out.println("In " + thrdName + ", count is " + count);
}
}
}
class UseThreads {
public static void main(String args[]) {
System.out.println("Main thread starting.");
MyThread mt = new MyThread("Child #1");
Thread newThrd = new Thread(mt);
newThrd.start();
for (int i = 0; i < 50; i++) {
System.out.print(".");
}
}
}
When you call start() on your thread, you get no guarantees on how fast it will start. This is up to the thread scheduler of your computer. If you run your code multiple times, you will likely get several different execution orders for your threads.
The call to begin a thread is asychronous. It does not wait until the thread has started running before returning; it returns essentially immediately.
You can implement that behaviour yourself, with a bit of locking, such that your main thread pauses until the thread you have begun issues a signal of some kind, to indicate it has begun execution.

Understand the concept of MultiThreading in Java

Recently I have gone through with one simple threading program, which leads me some issues for the related concepts... My sample program code looks like :
class NewThread implements Runnable {
Thread t;
NewThread() {
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start(); // Start the thread
}
public void run() {
try {
for (int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ThreadDemo {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for (int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
Now this program giving me the output as follows :
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
So, that's very much clear to me. But as soon as I am replacing the object creation code (calling of a NewThread class constructor) to as follows :
NewThread nt = new NewThread(); // create a new thread
the output becomes a bit varied like as follows :
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Child Thread: 3
Main Thread: 4
Child Thread: 2
Child Thread: 1
Main Thread: 3
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
And some times it's giving me same output in both the cases. So, i am not getting the exact change in both the scenario.
I would like to know that you the variation in the output is coming here ?
Thanks in advance...
The changed output is due to nature of both OS process scheduling and JVM thread scheduling. Even if you take out the second thread there is no guarantee that your thread will wake-up exactly after 500ms.
I'm not sure I understand the change that you mention, but the scheduling is non-deterministic, i.e., it may schedule the threads differently in different runs of the application.
Another thing; creating and starting a new thread in the constructor isn't really best practice. Have you considered letting NewThread extend Thread? Like this:
class NewThread extends Thread {
NewThread(String str) {
super(str);
System.out.println("Child thread: " + this);
}
public void run() {
try {
for (int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
public class ThreadDemo {
public static void main(String args[]) {
new NewThread("Demo Thread").start();
try {
for (int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
You have two threads, one which does something about every half second, one which does something about every second.
The JVM and OS makes no guarantee which of the threads available for scheduling gets run at a given time. Alternatively, if you have multiple cores then both threads could be running at the same time, and competing for a lock on the System.out that stops two threads printing at the same time - if you send the output one character at a time instead of using println, then the characters from both thread's output might be mixed together.
Your output shows that at one second and at two seconds, which of the two threads prints its output it is not predictable. This is as expected.
It makes no difference in this case whether or not you assign the NewThread object to a local variable. The object is not eligible for garbage collection while the thread it is running in is running (assuming Threads hold a reference to their runnable), and nothing else uses the local variable. So the difference after that change in the code is just the randomness in the scheduling, not the effect of the change.
As mentioned above, this is normal behaviour. If you need some tasks started at a specific time and/or at a fixed interval, then the Timer's scheduleAtFixedRate() may give you a better result.
Are both outputs correct for both programs? Yes.
The answer is the output is undefined. The particular (correct) output you get each time could depend on just about anything, including minor variations in the compiled bytecode. (It might be worth checking this with javap -c, just to be sure the difference in code is a possible cause.)
In general if you have two threads doing things in parallel, you can't be sure of the ordering of their combined output unless you synchronise them somehow.

Categories

Resources