Understand the concept of MultiThreading in Java - 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.

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.

Can we Access Synchronized method and an unsynchronized method of same instance from multiple threads at the same time?

It might seem to be a very naive question but I cannot find any concrete answer anywhere. I tried it even practically but since we cannot predict the behaviour of threads resource allocation in Java, it's really difficult to determine.
I just want to know if I can access a synchronized method and and unsynchronized method of a class at the same time from two different threads of same instance of that class ?
Don't see any problems. Try out this:
public class Main {
public static final SyncNotsynced sn = new SyncNotsynced();
public static void main(String[] args){
Thread t1 = new Thread(sn::synced);
Thread t2 = new Thread(sn::notsynced);
t1.start();
t2.start();
}
public static class SyncNotsynced {
public synchronized void synced(){
System.out.println(Thread.currentThread().getName() + " enter synced");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + " exit synced");
}
public void notsynced(){
System.out.println(Thread.currentThread().getName() + " enter notsynced");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + " exit notsynced");
}
}
}
or take look at the live example :). As you can see enterings of Thread 1 and Thread 2 are both happened before exiting:
Thread-0 enter synced
Thread-1 enter notsynced
Thread-0 exit synced
Thread-1 exit notsynced
For a formal explanation you can read JLS 17, but in short only one thread can enter a synchronized block on the same object monitor.
Btw, I used Thread.sleep because (emphasize mine):
Thread.sleep causes the currently executing thread to sleep
(temporarily cease execution) for the specified duration, subject to
the precision and accuracy of system timers and schedulers. The thread
does not lose ownership of any monitors, and resumption of execution
will depend on scheduling and the availability of processors on which
to execute the thread.

Query about threads in 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.

synchronized thread execution

my task is to create thread in this order: if A start->start B and C, if B start->start D.
And destroy them in reverse order If D then B. If B and C then A. I hope you get it. I manage to do it but I guess there is better way to do it. Do you have any suggestions?
After your comments i have changed my code and it is much more simply. But now it looks "stupid". I would like to change hardcore of if statements and implementation, any advice? tnx for advice I'm learning with you.
This is my new code:
import java.util.*;
class RobotController implements Runnable{
String name;
public void run() {
Thread t = Thread.currentThread();
System.out.println(t.getName() + " status = " + t.isAlive());
System.out.println(t.getName() + " status = " + t.getState());
}
public static void main(String args[]) throws InterruptedException{
Thread thread_A = new Thread(new RobotController(), "Thread A");
Thread thread_B = new Thread(new RobotController(), "Thread B");
Thread thread_C = new Thread(new RobotController(), "Thread C");
Thread thread_D = new Thread(new RobotController(), "Thread D");
thread_A.start();
thread_A.join();
System.out.println(thread_A.getState());
thread_B.start();
thread_B.join();
System.out.println(thread_B.getState());
thread_C.start();
thread_C.join();
System.out.println(thread_C.getState());
thread_D.start();
System.out.println(thread_D.getState());
}
}
There are some flaws in your code which will make it not to work accordingly sometimes:
You called thread_A.start() and then checked thread_A.isAlive(). Now what if , thread_A is already completed before thread_A.isAlive() condition is checked?.thread_B and thread_C is never started. Your application fails.
Assume that thread_A is not completed and thread_A.isAlive() condition is passed, then starting of thread_B before thread_C is not always guaranteed by Java thread scheduler. Again your application fails.
Assume that thread_B starts before thread_C and if thread_B completes before thread_B.isAlive() is checked then the if condition fails and thread_D is never started. Again your application fails.
Now a point to ponder:
There is no need to check if the thread is alive after its join() method is called. It is an unnecessary runtime overhead.
EDIT
OK, Here is the modified version of code..I hope it would let you understand the dynamics of thread:
class RobotController implements Runnable
{
private final Object lock = new Object();
private void notifyThread()
{
synchronized(lock)
{
lock.notify();
}
}
public void run()
{
synchronized(lock)
{
try
{
System.out.println(Thread.currentThread().getName() + " started");
lock.wait();
System.out.println(Thread.currentThread().getName()+ " stopped");
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
public static void main(String args[]) throws InterruptedException
{
RobotController rca = new RobotController();
RobotController rcb = new RobotController();
RobotController rcc = new RobotController();
RobotController rcd = new RobotController();
Thread thread_A = new Thread(rca,"Thread A");
Thread thread_B = new Thread(rcb,"Thread B");
Thread thread_C = new Thread(rcc,"Thread C");
Thread thread_D = new Thread(rcd,"Thread D");
thread_A.start();
while (thread_A.getState() != Thread.State.WAITING)
{
Thread.sleep(100);
}
thread_B.start();
thread_C.start();
while (thread_B.getState() != Thread.State.WAITING && thread_C.getState() != Thread.State.WAITING)
{
Thread.sleep(100);
}
thread_D.start();
while (thread_D.getState() != Thread.State.WAITING)
{
Thread.sleep(100);
}
rcd.notifyThread();
thread_D.join();
rcc.notifyThread();
thread_C.join();
rcb.notifyThread();
thread_B.join();
rca.notifyThread();
}
}
And here is the output:
Thread A started
Thread B started
Thread C started
Thread D started
Thread D stopped
Thread C stopped
Thread B stopped
Thread A stopped
In multi threading, there is no need of synchronization unless the common data is shared by multiple threads.
In your case, you want to start and stop the threads in a particular order. For this, there is join method in Thread class. This link shows good example of join method.
In my opinion, it is quite strange to use synchronized (lock) in your run method to lock your object. The reason is that in each Thread object has the different lock attribute, which is belong to each object. It means you are trying to lock the different objects. Actually, it doesn't make sense.
Basically, the object that you should apply the synchronized are any shared objects. For example, you need to count something and then you create a class object to share it in your class. In this case, it should be locked while being read or written.
I would like to highlight two points here:
Have a look at thread execution life cycle here. It says that, when start() method is called, thread enters in runnable state and not in running state. When thread enters in running state, that means run() method is getting exexuted. CPU/OS decides the priority of which thread should be transferred from runnable to running thread. E.g. if you call start() method for 4 threads, it is not necessary that they will execute in that particular order. (Running the same program in my pc multiple times gives me different outputs.
In your case, when the condition if(thread_A.isAlive()) is executed, it is possible that the thread A may not be in running state. Hence, the control will not go into if which is not correct.
To correct this behavior, in main, a while loop should implemented which waits until the thread becomes alive and so on.
2 . In your program, you have not assigned names to the threads and you are printing the name in the run() method. In this case, JVM assigns the names to threads in order of their execution e.g. first thread to execute will have name as 'Thread-0' and so on. Hence, we will not be able to identify which thread executed first. Assign the names using setName() method.

Java Thread concept / demo

I'm trying to write a Java program that uses threads. I want to be able to run 3 threads when the program starts, and have them waiting on an ArrayList of "work orders".
Initially, theere will be no work orders. So the Threads should just wait.
At some point in the future, work orders will be added to the ArrayList, and the main thread must notify the threads that there is work to do.
I want to be able to do it by extending Thread (instead of implementing Runnable).
I think the main issue I have is that the threads are not correctly synchronized with the workorders ArrayList.
My code looks like this:
public static void main(String[] args) {
AnotherRunnable anotherRunnable = new AnotherRunnable();
ArrayList<ATMRunnable> workOrders = new ArrayList<ATMRunnable>();
T1 t1 = new T1(anotherRunnable, workOrders);
T1 t2 = new T1(anotherRunnable, workOrders);
t1.start();
t2.start();
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
synchronized (workOrders){
System.out.println(t1.getState() + " - " + t1.getName());
System.out.println(t2.getState() + " - " + t2.getName());
System.out.println("notify");
workOrders.notify();
System.out.println(t1.getState() + " - " + t1.getName());
System.out.println(t2.getState() + " - " + t2.getName());
}
}
The AnotherRunnable class:
public class AnotherRunnable implements Runnable {
public void run()
{
System.out.println("AnotherRunnable");
}
}
And the Tread class:
public class T1 extends Thread {
AnotherRunnable anotherRunnable;
ArrayList<ATMRunnable> workOrders;
ATMThread(AnotherRunnable anotherRunnable, ArrayList<ATMRunnable> workOrders)
{
this.anotherRunnable = anotherRunnable;
this.workOrders = workOrders;
}
public void run()
{
System.out.println("Run Thread");
synchronized (workOrders){
try{
System.out.println("wait Thread");
workOrders.wait();
}
catch (InterruptedException e){}
}
}
}
This is the output of the program:
Run Thread
wait Thread
Run Thread
wait Thread
WAITING - Thread-1
WAITING - Thread-2
notify all
BLOCKED - Thread-1
WAITING - Thread-2
As you can see, the state of the first thread is changed to Blocked, after the call to notify on the workOrders object. But neither the threads nor the runnable object is executed.
Any help will be appreciated.
You should use concurrent collections in java to avoid manual synchronization as far as possible.
I want to be able to run 3 threads when the program starts, and have them waiting on an ArrayList of "work orders". Initially, theere will be no work orders. So the Threads should just wait. At some point in the future, work orders will be added to the ArrayList, and the main thread must notify the threads that there is work to do.
For this kind of synchronization, Blocking queues are your friends like LinkedBlockingQueue which make threads wait when there's no item in the queue or when the queue is full. You do not need any synchronized/wait/notify there.
You can also check if it helps: synchronization is risky
If it is only for learning purpose, you have to make your synchronization proper first logically. It doesn't use any condition for waiting or notifying which is problematic. It'll work if it is proper but its not a preferred way.
I found what I had to do to get this working. Mainly, it was the concept what was missing. I had to loop in the run method of the thread. I was thinking that that method would be called every time notifyall is invoked, which is not true. When wait() is call on the synchronized object, the thread is stopped, and with notify it resumes execution, if that code is not in a loop, it wont be executed.

Categories

Resources