java multithreading - child thread does not start immediately - java

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.

Related

Thread execution after .start() method

I am wondering what happens in the following scenario:
Two threads are created:
Thread t1 = new Thread();
Thread t2 = new Thread();
Assume these just print out a string, the threads then call the .start() method:
t1.start();
t2.start():
My question is why do these threads print in a seemingly random order each time? I know threads execute concurrently but would t1 not always finish before t2 due to the sequential execution of the main process?
Calling start() on a Thread doesn't necessarily result in the thread running immediately after. It is possible for other things to happen in between your calling start() and the first line of your thread's run() method actually being run. And even once your run() is actually running, it's also possible that other things happen before, during, or after your run() method finishes.
In your question, you said: "assume these just print out a string" – here's an implementation of run() which does that:
public void run() {
System.out.println("my name is: " + getName());
}
So it's possible that t1 starts to run first, but before it actually calls System.out.println, t2 is allowed to execute and runs to completion, then t1 is resumed.
If this kind of behavior won't work for your use case, you'll need to add some kind of concurrency protection to coordinate how and when your threads run.
UPDATE:
To illustrate the unpredictable sequence of thread execution, run this code a few times and observe the output:
public class Example {
public static void main(String[] args) {
for (int k = 0; k < 10; k++) {
new TestThread(k).start();
}
}
}
class TestThread extends Thread {
private final int k;
TestThread(int k) {
this.k = k;
}
#Override
public void run() {
System.out.print(k + " ");
}
}
Here is the output from one of my local runs:
7 0 1 5 4 6 3 2 8 9
Thread.start() doesn't guarantee execution. It will just make the Thread state runnable and hand over to the Thread Scheduler. It is the Thread Scheduler which decides which thread to run when.
If you need code to execute in a defined order on multiple threads, you need to add synchronization code between those threads.
Otherwise, the system is free to schedule execution in any order it sees fit.

notifyAll() not awakening processes

I'm programming a little Java program where I need to create threads (philosophers in my code), and these philosophers need to change of state between thinking, hungry and eating.
I'm not that far into the project and I have the next problem:
public class NewMain {
static Philosopher [] p;
public static void main(String[] args) {
p = new Philosopher[5];
p[0] = new Philosopher(0);
p[1] = new Philosopher(1);
p[2] = new Philosopher(2);
p[3] = new Philosopher(3);
p[4] = new Philosopher(4);
for (int i = 0; i<5; i++) {
try{
p[i].run();
if(i == 4) {
p.notifyAll();
}
}
catch(IllegalMonitorStateException e) {}
}
}
}
I'm creating 5 philosophers(threads). Each one of those has a wait() instruction in their code:
#Override
public void run() {
int rand;
if (status == 0) {
System.out.println("Philosopher " + id + " is waiting.");
try {
wait();
System.out.println("Awoken");
while(status == 0) {
System.out.println("Philosopher " + id + " is thinking.");
sleep(100);
rand = ThreadLocalRandom.current().nextInt(0,100);
if(rand > 95){
status = 1;
System.out.println("Philosopher " + id + " changed state to hungry.");
}
}
}
catch(InterruptedException e) {
System.out.println("Error!");
}
catch(IllegalMonitorStateException e) {}
}
}
The problem is that when invoking notifyAll(), the processes don't awake and they just die after executing the run() method of each thread.
If anyone is wondering, I'm not using synchronized because I need to run the methods at the same time.
Also, I've tried to put notifyAll() inside the run() method of the threads.
Can anyone tell me what's going on and why are the threads not continuing
with their code?
Problems
notify[All]() and wait() should be used on the same instance. You are notifying on the array Philosopher[] p, but waiting on this which is a Philosopher. It's like I am waiting for you, but you are notifying Sarah that you're going to be late.
You have created the threads but haven't started them properly. Calling run will execute the method in the current thread. Use the method start instead. It begins execution concurrently.
To use x.notify[All]() or x.wait(), you have to be within a synchronised block synchronized(x) { ... }. Ignoring IllegalMonitorStateException won't help you at all.
Answers
... why are the threads not continuing with their code?
They might call wait after the 4th thread notifies them.
... the processes don't awake and they just die ...
They don't die, they still wait until you terminate the program.
I'm not using synchronizedbecause I need to run the methods at the same time
You need to run the methods at the same time correctly, right? Here, synchronisation is required at least for building wait-notify communication.
p is an array of Runnable. when you write
p[i].run();
Then, you are invoking run method (actually you haven't started a thread here instead called run method) using object stored at p[i] location. Now, as per notifyAll
Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods.
You should have used start() instead run() to start a new thread.
notify() and notifyAll are used when thread(s) are waiting to acquire monitor on current object.

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.

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.

How to Synchronize Threads

In this multithreading program, when I run it, I always get the output in some random order. But I was wondering if there is any way I can make this program to work in synchronized mode. Like when I runt it then for the first thread it should print out everything, then for second thread it should print out something, then for third thread it should print out everything etc etc. So sample output should be like this for each thread-
Task 1 Started
original: Hello World
Difference:- 0
Task 1 Ended
Task 2 Started
original: Hello World
Difference:- 0
Task 2 Ended
............
............
Task 15 Started
original: Hello World
Difference:- 0
Task 15 Ended
This is my below program. Any suggestions will be appreciated.
class ThreadTask implements Runnable {
private int id;
public ThreadTask(int id) {
this.id = id;
}
public synchronized void run() {
System.out.println("Task " + id + " Started ");
String originalString = "Hello World";
System.out.println("original: " + originalString);
System.out.println("Task " + id + " Ended ");
}
}
public class TestPool {
public static void main(String[] args) throws InterruptedException {
int size = 5; //Integer.parseInt(args[0]);
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(size);
// queue some tasks
for(int i = 1; i <= 3 * size; i++) {
service.submit(new ThreadTask(i));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
You commented on Jakub's answer as follows:
Can you give me example basis on my code as I just started learning about threading. It will be of great help to me.
What Jakub is saying is that forcing threads to run in a fixed sequence defeats the purpose of using threads in the first place. Think about this.
If you really do want / need your example to run the tasks in order, you may as well do this:
for (int i = 1; i <= 3 * size; i++) {
new ThreadTask(i).run();
}
i.e. just run the runnables in the current thread.
Or you could set the maximum pool size to 1, which forces the service to run the tasks in order. (Of course, this defeats the point of using threads. You won't get any parallelism this way.)
A more sensible approach would be to have each thread return its results in a Future, and then have the main thread fetch the value from each future (in the required order) and print it. Basically, you want to allow the threads to run in any order (and in parallel, if you have multiple cores), but then impose the ordering when you access the results.
The essence of thread is that they can run simultaneously, if you want them to run in order, simply do not use Thread.
There's another kind of requirement, that maybe you want several jobs to work together (simultaneously), but in a given order. In this case, I highly suggest you to implement a queuing system. That is, build a queue like
Queue <C> q
And a thread
class T implements Runnable {
public void run() {
while (!q.empty()) {
// Do something
}
}
}
You can use Runnable through ExecutorService, like the code that you've used.
You can also add some elements into the queue in "Do something" section of previous code, then you can control the order of jobs by yourself.
You can save the the reference to the previous thread and hook up the next thread to the previous one using join(). That will ensure the threads will be run in a series (next one not starting unless the previous one finished). But the point of doing that is eluding me.
public class TestPool
{
static class ThreadTask extends Thread
{
private int id;
private Thread previous;
public ThreadTask(int id, Thread previous){
this.id = id;
this.previous = previous;
}
public void run(){
if(previous != null){
try{
previous.join();
}
catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("Task " + id + " Started ");
String originalString = "Hello World";
System.out.println("original: " + originalString);
System.out.println("Task " + id + " Ended ");
}
}
public static void main(String[] args) throws InterruptedException{
int size = 5; // Integer.parseInt(args[0]);
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(size);
Thread previous = null;
// queue some tasks
for(int i = 1; i <= 3 * size; i++){
Thread thread = new ThreadTask(i, previous);
previous = thread;
thread.start();
//service.submit(thread);
}
// wait for termination
//service.shutdown();
//service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
Not tested, sry. I don't also know what the ExecutorService is doing, it might break this. Note that I need to be a Thread, being Runnable is not enough. Also, run() needs not be synchronised, as it will be called only once per execution. And you should not start the threads with run(), but with start().
EDIT: I just tried to run it, and the ExecutorService is fu**ing things up. If you just start the thread (like the my code does), then it's working.

Categories

Resources