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.
Related
I'm trying to figure out how to use wait & notify, so I've written this small example with a few planes waiting for a runway to clear before they take off, the issue I'm having is that when a plane takes off, and calls notifyAll(), only one thread seems to be woken up, i.e. I expect all of the threads to report that they have been notified, but are still waiting. What actually happens is that only one thread is woken, and the rest do nothing. Why does it appear that only the one thread is woken, and how can I fix it?
class Plane extends Thread
{
Runway runway;
Plane(int id, Runway runway)
{
super(id + "");
this.runway = runway;
}
public void run()
{
runway.taxi();
runway.takeoff();
}
}
class Runway
{
boolean isFull;
Runway()
{
isFull = false;;
}
public synchronized void taxi()
{
System.out.println(Thread.currentThread().getName() + " started to taxi");
while(isFull)
{
System.out.println(Thread.currentThread().getName() + " is queued");
try
{
wait();
}
catch(InterruptedException e){}
}
isFull = true;
System.out.println(Thread.currentThread().getName() + " entering runway");
}
public synchronized void takeoff()
{
try
{
Thread.currentThread().sleep(1000);
}
catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName() + " took off");
isFull = false;
notifyAll();
}
public static void main(String[] args)
{
Runway runway = new Runway();
new Plane(1, runway).start();
new Plane(2, runway).start();
new Plane(3, runway).start();
new Plane(4, runway).start();
}
}
Thanks for taking the time to help me :)
Because notifyAll() is not wakeAll(). All threads are notified, but only one gets hold of the key and is being run. All others get to waiting pull again.
Suppose you have 4 Planes that are all start()-ed one after the other.
All 4 will attempt to call taxi() followed by takeoff()
The first one will call taxi():
acquire the lock,
find isFull is false
set isFull to true
return, releasing the lock
Then one (or more) of the remaining threads may get to call taxi(). If they do, they:
acquire the lock
find isFull is false
call wait() which releases the lock
OR
block while trying to acquire the lock
In the mean time, the thread that returned from taxi() will call takeoff(). This will:
acquire the lock
sleep for 1 second,
notify any threads that were waiting
return, releasing the lock.
So how does this explain what you are seeing?
Suppose that when the first thread returned from taxi() it was immediately able to reacquire the lock and start the takeoff() call. It would then call sleep() WHILE HOLDING THE LOCK. This would prevent any other threads from starting their taxi() calls (if they hadn't already done so). Then after the sleep, it would call notifyAll(). But that would only notify the threads that were had gotten into the taxi() call and that had called wait(). Any threads that were blocked while starting the taxi() call would never see the notifications.
(Notifications are never queued for threads that are not in wait() calls.)
Is this likely? Well yes it is.
Starting a thread is a relatively expensive / time consuming process, and there is a good chance that the first thread started will get to do a lot of work before the next one gets started. The chances are that it will get all the way to the sleep call before the second one tries to call taxi().
The same pattern is likely to repeat for the remaining threads. When each thread that gets into taxi() is likely to release and then reacquire it before another thread is scheduled. (Thread scheduling is handled by the OS, and it is optimizing for efficiency rather than fairness. If you want fair scheduling, you need to use a Lock object.)
... how can a fix it?
Change your code so that you don't sleep while holding the lock. For example:
public void takeoff() {
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
// squash ...
}
System.out.println(Thread.currentThread().getName() + " took off");
synchronize (this) {
isFull = false;
notifyAll();
}
}
That's what it does. It "notifies" all the waiting threads, but only one wakes and gets the CPU. notify() picks a waiting thread based on what the underlying thread implementation selects. notifyAll() gives all the waiting threads an equal chance to compete. But either way, only one thread takes the context.
I have this Question :
Create and run a thread that writes "Hello friends" on screen. The main Thread waits for it only 500 milliseconds. Then run the program again after you give the created Thread lower priority than the main Thread. This time, the main Thread should wait for it 10 milliseconds. Do you notice anything? Why?
I want to know the difference that made by Thread.setPriority(n)
first code and second get the same output
first code
public class Q2 {
public static void main(String[] args) {
Thread2 myThread = new Thread2();
myThread.start();
System.out.println("main thread");
}
}
class Thread2 extends Thread{
#Override
public void run(){
try {
join(500);
System.out.println("Hello Friends from thread2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
seconde code
public class Q2 {
public static void main(String[] args) {
Thread2 myThread = new Thread2();
myThread.start();
System.out.println("main thread");
}
}
class Thread2 extends Thread{
#Override
public void run(){
try {
setPriority(MIN_PRIORITY);
join(500);
System.out.println("Hello Friends from thread2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
the main Thread should wait for it 10 milliseconds
That's not what your code does. The join should be in the main thread, not in the newly created thread:
Thread2 myThread = new Thread2();
myThread.start();
myThread.join(10);
I assume the whole idea of this exercise is to see the difference between two threads with different priorities. Giving a thread a lower priority may delay its scheduled execution. When the main thread waits for a smaller duration for the new thread to finish, the outputs of the two threads may interleave since the main thread may continue to reach the System.out before the second thread does.
The documentation of the Thread class explains what a thread priority is:
Every thread has a priority. Threads with higher priority are executed in preference to threads with lower priority.
In general, don't extend Thread, you should wrap a Runnable instead.
The Thread priority is
just a hint, the OS can and does ignore it if you don't have the right permissions.
It will only matter if you don't have free CPU. If you have free CPU every thread which wants to run can run.
it really won't matter if you are putting your thread to sleep. e.g. a join.
The only difference it could make is when your machine is very busy, it would take a little longer to wake up from the sleep. e.g. instead of taking say 500 to 501 ms to do the join, it might take 510 ms sometimes.
how can I use join method ?
The purpose of join is to wait for another thread to finish up to some time limit. If you join on yourself, this is effectively the same as Thread.sleep I suggest using Thread.sleep instead as this is less confusing.
First, from the documentation for Thread:
Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
So when you have two Thread instances, lets say the current one and a new one, you can cause the current thread to wait for the new one to die:
final Thread t = new Thread(() -> System.out.println("Test"));
t.start();
t.join();
So now our current thread (the one creating t) will wait for t to die, then continue. This method makes an asynchronous task synchronous.
Now, what does calling join in a Thread do? Well, it means that the thread will wait for itself to die. This is the same as TimeUnit.MILLISECONDS.sleep().
So what does your code actually do?
Well, main calls the following code:
Thread2 myThread = new Thread2();
myThread.start();
System.out.println("main thread");
There is nothing here that makes main wait for anything, main dies.
Now your Thread2 (terrible name for a class) does the following:
setPriority(MIN_PRIORITY);
join(500);
System.out.println("Hello Friends from thread2");
So it sets its own priority, it then waits for 500 milliseconds for itself to die. Obviously it doesn't die in that time. It then prints.
TL;DR: setPriority does next to nothing in this code
One further note, do not extends Thread, use a Runnable.
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
ExampleTest obj = new ExampleTest();
Thread t1 = new Thread(new Runn(obj));
Thread t2 = new Thread(new Runn(obj));
Thread t3 = new Thread(new Runn(obj));
t1.start();
t2.start();
t3.start();
//Thread.sleep(1);
obj.exit();
}
}
class ExampleTest {
public synchronized void enter() {
try {
System.out.println("printed " +Thread.currentThread().getName() +" inside wait");
this.wait();
System.out.println("printed " +Thread.currentThread().getName() +" exit wait");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("printed " +Thread.currentThread().getName() +" at time: "+System.currentTimeMillis());
}
public synchronized void exit() {
this.notifyAll();
}
}
class Runn implements Runnable {
ExampleTest obj;
public Runn(ExampleTest obj) {
this.obj = obj;
}
#Override
public void run() {
obj.enter();
}
}
what is the role of notifyAll(). Will notifyAll() allows all the waiting thread to acquire lock sequentially in random order or only one thread can acquire the lock?
Without the sleep statement the statement obj.exit(); will be very likely be executed before all of your threads reaching their wait status. ie. the notifyAll call will be over before at least one of your thread is in wait status. So at least one of your threads will be stuck in wait status waiting for some other thread to notify it and wake up. But that will never happen as obj.exit() is already finished.
With your sleep statement in place , all of your threads will get a chance to reach their wait status and your notifyAll call after the sleep will wake them all, The order of waking up will not be deterministic and will be handled by the thread scheduler.
Your code suffers from the "lost notification" syndrome, which is alleviated (but not deterministically avoided) by the sleep call.
You haven't provided any mechanism which would ensure that, at the time of calling exit, all the threads have already reached their wait call. Therefore some threads will miss the notification and enter an eternal wait state.
The notifyAll call does wake up all waiting threads, but it doesn't wake up threads which enter the wait state in the future.
With the following code:
t1.start();
t2.start();
t3.start();
You are starting the threads. Starting threads might take some time as it involves memory allocation and other operations. When your threads run they enter a wait state. Started threads do not, however, execute immediately. They start executing as soon as the scheduler decides it is time for them to execute. When you call start the main thread is currently running on the CPU. Without the sleep most likely the main thread will keep the CPU and call:
obj.exit();
Before the threads actually started, that is, before the threads actually entered the wait state. The notifyAll will execute in vain, as threads are not started yet and therefore are not waiting. The notification will be lost.
With the sleep call you are suspending the main thread for quite some time (for the CPU perspective). This means that the other threads will most likely get the CPU and enter the wait state. So when you then call notifyAll this time the notification will not get lost. Notice that there is no guarantee that this will happens: it might still happen that when you call exit() some (or all) other threads have not yet executed their wait.
According to the basic definition of synchronized method from source - link
"When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object."
and I read about the wait() that it releases a lock before it sleeps. There is a confusion here if wait releases the lock then other thread can get-into the synchronized method and does it make sense because it may lead to race condition?
Here is my sample code that is allowing one and two thread into the synchronized block.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Ashish Pancholi
*/
public class Test {
public Test() {
Sharing sharing = new Sharing();
Worker worker_ = new Worker(sharing);
Thread thread_ = new Thread(worker_, "one");
Worker worker = new Worker(sharing);
Thread thread = new Thread(worker, "two");
thread_.start();
thread.start();
}
public static void main(String[] argu) {
Test test = new Test();
}
public class Worker implements Runnable {
private Sharing sharing;
public Worker(Sharing sharing) {
this.sharing = sharing;
}
#Override
public void run() {
sharing.check();
}
}
public class Sharing {
public void check() {
synchronized (this) {
System.out.println("Thread IN " + Thread.currentThread().getName());
try {
wait(5000);
} catch (InterruptedException ex) {
}
System.out.println("Thread OUT " + Thread.currentThread().getName());
}
}
}
}
Output-
Thread IN one
Thread IN two
Thread OUT one
Thread OUT two
Yes it makes sense.
The API of the wait() method says:
Causes the current thread to wait until either another thread invokes
the notify() method or the notifyAll() method for this object, or a
specified amount of time has elapsed.
So if the wait method would NOT release the lock on the monitor object, no other thread could get it and thus no other thread could invoke notify or notifyAll on that monitor object.
The wait(5000) means that the current thread will wait up to 5000 milliseconds for a notification before continuing or continue after 5000 ms. If you want to hold the lock and pause 5000 ms then you must use Thread.sleep(5000).
It makes sense that there might be race conditions. Race conditions naturally happen when dealing with multiple threads. It is your job to prevent them by carefully managing your threads, and the wait method is an important tool that you can use to help with that.
Normally you wouldn't simply call wait with a fixed 5-second pause like that. In a real application you would probably be waiting for some specific condition to be true, so your wait looks more like this:
try {
while(!condition) {
wait();
}
doSomething();
} catch(InterruptedException e) {
doSomethingElseWhenWeAreAskedNotToWait();
}
Whether you have a race condition depends upon when condition becomes true, who else might be waiting for that condition, and what everyone does when it happens. The reason wait gives up the lock is to give condition a chance to become true while we wait.
You are using synchronized with two different locks, so there is no synchronization happening between the two threads.
Synchronize on the instance of Test rather than Sharing, and the behaviour will be quite different.
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.