Sorry for my bad formatting. I am using a notepad to write my programs.
This is a working code. The only question I have is, I have read that notify and wait must be used in a Synchornized block. However, in the following example, wait and notify are not used in a synchronized block and still no error is thrown.
class counthrd implements Runnable {
Thread thrd;
String x;
counthrd cnt1;
counthrd() {
}
boolean suspended;
boolean stopped;
counthrd(String s, counthrd cnt1) {
thrd = new Thread(this, s);
this.cnt1 = cnt1;
thrd.start();
x = s;
}
public void run() {
try {
System.out.println("Starting " + thrd.currentThread().getName());
for (int i = 1; i < 100; i++) {
System.out.print(i + " ");
if ((i % 10) == 0) {
System.out.println();
Thread.sleep(500);
}
//synchronized(cnt1){
while (suspended) {
System.out.println("going to wait mode");
wait();
notify();
}
//}
}
} catch (Exception e) {
System.out.println(e);
}
}
synchronized void suspendme() {
suspended = true;
notify();
}
synchronized void resumeme() {
suspended = false;
notify();
}
}
class counter {
public static void main(String args[]) throws InterruptedException {
counthrd cnt1 = new counthrd();
counthrd cnthrd1 = new counthrd("thrd 1", cnt1);
Thread.sleep(1000);
System.out.println("going to wait mode");
cnt1.suspendme();
Thread.sleep(1000);
System.out.println("resuming");
cnt1.resumeme();
Thread.sleep(1000);
}
}
See my comment. Since IllegalMonitorStateException is never thrown, we know that wait is never being called.
Notice you have two instances of counthrd...
counthrd cnt1 = new counthrd();
counthrd cnthrd1 = new counthrd("thrd 1", cnt1);
See which instance you're calling suspendme and resumeme on?
Thread.sleep(1000);
System.out.println("going to wait mode");
cnt1.suspendme();
Thread.sleep(1000);
System.out.println("resuming");
cnt1.resumeme();
Thread.sleep(1000);
cnt1 is initialized using your no-arg constructor, seen here:
counthrd() {
}
The point is that cnt1 never actually starts its own thread. It never does anything, really. cnthrd1 is the one that starts a thread, as seen here:
counthrd(String s, counthrd cnt1) {
thrd = new Thread(this, s);
this.cnt1 = cnt1;
thrd.start();
x = s;
}
The point to make is that suspended is an instance field, and not shared between cnt1 and cnthrd1. Modifying cnt1.suspended will not cause cnthrd1 to go into "wait mode". wait is never called, and thus the exception is never thrown.
To demonstrate, try calling suspendme and resumeme on cnthrd1, instead... :-)
C:\dev\scrap>javac counter.java
C:\dev\scrap>java counter
Starting thrd 1
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
going to wait mode
going to wait mode
java.lang.IllegalMonitorStateException
resuming
That being said, I figured I'd suggest you do some stuff that your code should be doing.
Declare suspended as volatile. Without some explicit memory ordering guarantees, there's no guarantee when or even if cnthrd1 reads the updated value of suspended.
Ditch the cnt1 field and instance; there's no reason for them. Get rid of that empty constructor, too.
Thread.currentThread is a static method; you don't need to use an instance for it. That all aside, thrd is guaranteed to equal Thread.currentThread here.
counthrd.x is equal to thrd.getName; why not just use x instead?
Use some better, more descriptive names. For example, instead of x, why not name? Instead of thrd, why not thread? Instead of counthrd, why not CountingThread?
You only need to call notify in resumeme, not suspendme. (in fact, calling notify in suspendme could accidentally trigger an InterruptedException if the thread is sleeping i.e. when (i % 10) == 0)
You also don't want notify in the while (suspended) loop. Your while loop can actually be turned into an if statement, too, now.
As previously stated, you need synchronized (this) around your code that calls while.
Avoid doing real logic in the constructor, e.g. thrd.start().
suspend doesn't need to be synchronized. resume doesn't need to be synchronized, either; only the wait and notify calls require it.
You can find a modified version of your example that works properly here.
Related
I have 2 matrices and I need to multiply them and then print the results of each cell. As soon as one cell is ready I need to print it, but for example I need to print the [0][0] cell before cell [2][0] even if the result of [2][0] is ready first. So I need to print it by order.
So my idea is to make the printer thread wait until the multiplyThread notifies it that the correct cell is ready to be printed and then the printerThread will print the cell and go back to waiting and so on..
So I have this thread that does the multiplication:
public void run()
{
int countNumOfActions = 0; // How many multiplications have we done
int maxActions = randomize(); // Maximum number of actions allowed
for (int i = 0; i < size; i++)
{
result[rowNum][colNum] = result[rowNum][colNum] + row[i] * col[i];
countNumOfActions++;
// Reached the number of allowed actions
if (countNumOfActions >= maxActions)
{
countNumOfActions = 0;
maxActions = randomize();
yield();
}
}
isFinished[rowNum][colNum] = true;
notify();
}
Thread that prints the result of each cell:
public void run()
{
int j = 0; // Columns counter
int i = 0; // Rows counter
System.out.println("The result matrix of the multiplication is:");
while (i < creator.getmThreads().length)
{
synchronized (this)
{
try
{
this.wait();
}
catch (InterruptedException e1)
{
}
}
if (creator.getmThreads()[i][j].getIsFinished()[i][j] == true)
{
if (j < creator.getmThreads()[i].length)
{
System.out.print(creator.getResult()[i][j] + " ");
j++;
}
else
{
System.out.println();
j = 0;
i++;
System.out.print(creator.getResult()[i][j] + " ");
}
}
}
Now it throws me these exceptions:
Exception in thread "Thread-9" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-6" Exception in thread "Thread-4" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-5" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-8" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-7" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-11" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-10" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-12" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at multiplyThread.run(multiplyThread.java:49)
line 49 in multiplyThread is the "notify()"..I think I need to use the synchronized differently but I am not sure how.
If anyone can help this code to work I will really appreciate it.
To be able to call notify() you need to synchronize on the same object.
synchronized (someObject) {
someObject.wait();
}
/* different thread / object */
synchronized (someObject) {
someObject.notify();
}
While using the wait and notify or notifyAll methods in Java the following things must be remembered:
Use notifyAll instead of notify if you expect that more than one thread will be waiting for a lock.
The wait and notify methods must be called in a synchronized context. See the link for a more detailed explanation.
Always call the wait() method in a loop because if multiple threads are waiting for a lock and one of them got the lock and reset the condition, then the other threads need to check the condition after they wake up to see whether they need to wait again or can start processing.
Use the same object for calling wait() and notify() method; every object has its own lock so calling wait() on object A and notify() on object B will not make any sense.
Do you need to thread this at all ? I'm wondering how big your matrices are, and whether there's any benefit in having one thread print whilst the other does the multiplication.
Perhaps it would be worth measuring this time before doing the relatively complex threading work ?
If you do need to thread it, I would create 'n' threads to perform the multiplication of the cells (perhaps 'n' is the number of cores available to you), and then use the ExecutorService and Future mechanism to dispatch multiple multiplications simultaneously.
That way you can optimise the work based on the number of cores, and you're using the higher level Java threading tools (which should make life easier). Write the results back into a receiving matrix, and then simply print this once all your Future tasks have completed.
Let's say you have 'black box' application with some class named BlackBoxClass that has method doSomething();.
Further, you have observer or listener named onResponse(String resp) that will be called by BlackBoxClass after unknown time.
The flow is simple:
private String mResponse = null;
...
BlackBoxClass bbc = new BlackBoxClass();
bbc.doSomething();
...
#override
public void onResponse(String resp){
mResponse = resp;
}
Lets say we don't know what is going on with BlackBoxClass and when we should get answer but you don't want to continue your code till you get answer or in other word get onResponse call. Here enters 'Synchronize helper':
public class SyncronizeObj {
public void doWait(long l){
synchronized(this){
try {
this.wait(l);
} catch(InterruptedException e) {
}
}
}
public void doNotify() {
synchronized(this) {
this.notify();
}
}
public void doWait() {
synchronized(this){
try {
this.wait();
} catch(InterruptedException e) {
}
}
}
}
Now we can implement what we want:
public class Demo {
private String mResponse = null;
...
SyncronizeObj sync = new SyncronizeObj();
public void impl(){
BlackBoxClass bbc = new BlackBoxClass();
bbc.doSomething();
if(mResponse == null){
sync.doWait();
}
/** at this momoent you sure that you got response from BlackBoxClass because
onResponse method released your 'wait'. In other cases if you don't want wait too
long (for example wait data from socket) you can use doWait(time)
*/
...
}
#override
public void onResponse(String resp){
mResponse = resp;
sync.doNotify();
}
}
You can only call notify on objects where you own their monitor. So you need something like
synchronized(threadObject)
{
threadObject.notify();
}
notify() needs to be synchronized as well
I'll right simple example show you the right way to use wait and notify in Java.
So I'll create two class named ThreadA & ThreadB. ThreadA will call ThreadB.
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();//<----Create Instance for seconde class
b.start();//<--------------------Launch thread
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();//<-------------WAIT until the finish thread for class B finish
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
and for Class ThreadB:
class ThreadB extends Thread{
int total;
#Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();//<----------------Notify the class wich wait until my finish
//and tell that I'm finish
}
}
}
Simple use if you want How to execute threads alternatively :-
public class MyThread {
public static void main(String[] args) {
final Object lock = new Object();
new Thread(() -> {
try {
synchronized (lock) {
for (int i = 0; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + ":" + "A");
lock.notify();
lock.wait();
}
}
} catch (Exception e) {}
}, "T1").start();
new Thread(() -> {
try {
synchronized (lock) {
for (int i = 0; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + ":" + "B");
lock.notify();
lock.wait();
}
}
} catch (Exception e) {}
}, "T2").start();
}
}
response :-
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
we can call notify to resume the execution of waiting objects as
public synchronized void guardedJoy() {
// This guard only loops once for each special event, which may not
// be the event we're waiting for.
while(!joy) {
try {
wait();
} catch (InterruptedException e) {}
}
System.out.println("Joy and efficiency have been achieved!");
}
resume this by invoking notify on another object of same class
public synchronized notifyJoy() {
joy = true;
notifyAll();
}
For this particular problem, why not store up your various results in variables and then when the last of your thread is processed you can print in whatever format you want. This is especially useful if you are gonna be using your work history in other projects.
This looks like a situation for producer-consumer pattern. If you’re using java 5 or up, you may consider using blocking queue(java.util.concurrent.BlockingQueue) and leave the thread coordination work to the underlying framework/api implementation.
See the example from
java 5:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html
or java 7 (same example):
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
You have properly guarded your code block when you call wait() method by using synchronized(this).
But you have not taken same precaution when you call notify() method without using guarded block : synchronized(this) or synchronized(someObject)
If you refer to oracle documentation page on Object class, which contains wait() ,notify(), notifyAll() methods, you can see below precaution in all these three methods
This method should only be called by a thread that is the owner of this object's monitor
Many things have been changed in last 7 years and let's have look into other alternatives to synchronized in below SE questions:
Why use a ReentrantLock if one can use synchronized(this)?
Synchronization vs Lock
Avoid synchronized(this) in Java?
This is a test code I have created to study threads. It consist of two threads assigned to the same Runnable. They have to deduct 5 to an int, and stop if the int is not big enough to deduct 5. Thing is, thread 1 "alpha" keeps looping until it is halfway within the loop, in this case being 5. Then thread 2 "beta" starts. It is an extrange behaviour I cannont comprehend. What am I missing?
public class synconizedThread implements Runnable {
int balance = 100;
public void run() {
checkAmmount();
}
public void checkAmmount() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()
+ "checks balance: " + balance);
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
withDrawAmmount();
}
}
}
public void withDrawAmmount() {
if (balance <= 0) {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Balance is " + balance + " not enough");
}
else {
balance = balance - 5;
System.out.println(Thread.currentThread().getName()
+ "Whitdraws, balance left: " + balance);
}
}
public static void main(String[] args) {
Runnable myJob = new synconizedThread();
Thread alpha = new Thread(myJob);
alpha.setName("alpha");
Thread beta = new Thread(myJob);
beta.setName("beta");
alpha.start();
beta.start();
}
}
You're synchronizing the entire loop, so the first thread enters the loop, then won't give up the CPU until after the loop completes.
Instead, you probably want to synchronize each iteration of the loop, that way the threads will have a chance to alternate.
You're also synchronizing the call to sleep(), which probably isn't what you want to do. You probably want to move that outside your synchronization.
public void checkAmmount() {
for (int i = 0; i < 10; i++) {
synchronized (this) {
System.out.println(Thread.currentThread().getName()
+ "checks balance: " + balance);
withDrawAmmount();
}
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
I see two issues:
The loop is within the synchronized block. So whoever gets that lock first executes the loop. Put the synchronized inside the loop. Then a thread will release the lock at the end of an iteration, and compete for it again at the beginning of the next, and you will have concurrency. For example, make the withDrawAmount() method synchronized. (If you do that, make sure to move the println of thread ID to inside the withDrawAmount().)
Thread.sleep() does not release the lock, so it's not like that fixes the problem of the loop being inside synchronized. You should probably take every Thread.sleep() call out altogether since they're just slowing things down.
As ever, you should try to keep the critical section - the piece inside synchronized - as small as possible, for maximum concurrency. Synchronizing withDrawAmount() should be fine, especially once you get rid of those sleep() calls. If you want to have some fun and try to see if you can get even bigger throughput, take a look at java.util.conccurent.atomic.AtomicInteger
Your first thread enters the synchronized block, loops for 10 iterations and withdraws 5 at each iteration, and then leaves the synchronized block.
So when the 10 iterations are done (and the balance is thus 50), it stops running, leaves the synchronized block, allowing the second thread to run and executes its 10 iterations.
It's the synchronized keyword. You have it around the whole for loop, so whoever gets to it first gets to run the entire for loop.
Thread B can't access the variable while Thread A is using it - it's locked by A.
If you want both to deduct at the same time you should move the synchronized inside the for loop.
As far as I understand your question, your problem is that thread alpha is already halfway through his loop until thread beta starts.
The synchronized keyword blocks all other thread from accesing the synchronized object. You could put the synchronized keyword inside the loop so that each thread enters and then leaves the monitor each time
ALso, by default, threads do not necessarily get the equal cpu time. So thread alpha starts working as soon as you invoke the start() method and is already halfway through until thread "beta" is even started by the main Thread
Can anyone explain this program on inter-thread communication?
// A correct implementation of a producer and consumer.
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
while(!valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
while(valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while(true) {
q.put(i++);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while(true) {
q.get();
}
}
}
class PCFixed {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}
Output
Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
......
It is very confusing as far as I am concerned, especially the put and get methods where notify() and wait() are used. Please also explain why a boolean value is used.
So there are 2 threads. Qne is setting values on this Q data structure and the other is reading them. Q uses a boolean flag to tell whether a new value is present, the flag gets cleared once an existing value is read.
Q.get uses wait to block until a new value is available to read. Once it's read the new value it sets the flag back to false.
Q.put waits until the other queue has read the new value before setting it to a new value, then lets the other thread know by setting the boolean flag and calling notify.
Remember that wait gives up the lock so the other thread can acquire it.
The boolean flag is needed because a thread may stop waiting without having been notified. Just because a thread woke up doesn't mean it got a notification. Also, even if the thread gets notified, since the thread gave up the lock when it started to wait, the current state of things is unknown (in general there are multithreaded programs where another thread might sneak in and snag something between the time a thread is notified and the time it can regain the lock) so the thread has to re-test the condition again once it has the lock.
Constructs like wait and notify are building blocks for large concurrent programs, so some things may not make as much sense in a small example with only two threads.
See basically its a multithreaded communication with synchronized methods.
simple rquirement here is
1)first allow to write for producer.
2)next allow to read for consumer.
that is controlled using boolean flag valueSet.
in case of producer means put method of Q, logic works this way
if the valueSet is is true means already write is done then ask put method called thread to wait. so it goes to wait until someone calls notify.
ofcourse it wont continue further logic and keeps on waiting for someone to call notify.
coming to reader means get() of Q,
if the valueSet is is false means writter is executing then ask get method called thread to wait. so it goes to wait until someone calls notify.
so once writer completes the execution it calls notify at the end and now reader threads awake and starts reading.
I want to stop a running thread immediately. Here is my code:
Class A :
public class A() {
public void methodA() {
For (int n=0;n<100;n++) {
//Do something recursive
}
//Another for-loop here
//A resursive method here
//Another for-loop here
finishingMethod();
}
}
Class B:
public class B() {
public void runEverything() {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
A a = new A();
a.methodA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
My problem is that i need to be able to stop the thread in Class B even before the thread is finished. I've tried interrupt() method, but that doesn't stop my thread. I've also heard about using shared variable as a signal to stop my thread, but I think with long recursive and for-loop in my process, shared-variable will not be effective.
Any idea ?
Thanks in advance.
Thread.interrupt will not stop your thread (unless it is in the sleep, in which case the InterruptedException will be thrown). Interrupting basically sends a message to the thread indicating it has been interrupted but it doesn't cause a thread to stop immediately.
When you have long looping operations, using a flag to check if the thread has been cancelled is a standard approach. Your methodA can be modified to add that flag, so something like:
// this is a new instance variable in `A`
private volatile boolean cancelled = false;
// this is part of your methodA
for (int n=0;n<100;n++) {
if ( cancelled ) {
return; // or handle this however you want
}
}
// each of your other loops should work the same way
Then a cancel method can be added to set that flag
public void cancel() {
cancelled = true;
}
Then if someone calls runEverything on B, B can then just call cancel on A (you will have to extract the A variable so B has a reference to it even after runEverything is called.
I think you should persevere with using Thread.interrupt(). But what you need to do to make it work is to change the methodA code to do something like this:
public void methodA() throws InterruptedException {
for (int n=0; n < 100; n++) {
if (Thread.interrupted) {
throw new InterruptedException();
}
//Do something recursive
}
// and so on.
}
This is equivalent declaring and using your own "kill switch" variable, except that:
many synchronization APIs, and some I/O APIs pay attention to the interrupted state, and
a well-behaved 3rd-party library will pay attention to the interrupted state.
Now it is true that a lot of code out there mishandles InterruptedException; e.g. by squashing it. (The correct way to deal with an InterruptedException is to either to allow it to propagate, or call Thread.interrupt() to set the flag again.) However, the flip side is that that same code would not be aware of your kill switch. So you've got a problem either way.
You can check the status of the run flag as part of the looping or recursion. If there's a kill signal (i.e. run flag is set false), just return (after whatever cleanup you need to do).
There are some other possible approaches:
1) Don't stop it - signal it to stop with the Interrupted flag, set its priority to lowest possible and 'orphan' the thread and any data objects it is working on. If you need the operation that is performed by this thread again, make another one.
2) Null out, corrupt, rename, close or otherwise destroy the data it is working on to force the thread to segfault/AV or except in some other way. The thread can catch the throw and check the Interrupted flag.
No guarantees, sold as seen...
From main thread letsvsay someTask() is called and t1.interrput is being called..
t1.interrupt();
}
private static Runnable someTask(){
return ()->{
while(running){
try {
if(Thread.interrupted()){
throw new InterruptedException( );
}
// System.out.println(i + " the current thread is "+Thread.currentThread().getName());
// Thread.sleep( 2000 );
} catch (Exception e) {
System.out.println(" the thread is interrputed "+Thread.currentThread().getName());
e.printStackTrace();
break;
}
}
o/P:
java.lang.InterruptedException
at com.barcap.test.Threading.interrupt.ThreadT2Interrupt.lambda$someTask$0(ThreadT2Interrupt.java:32)
at java.lang.Thread.run(Thread.java:748)
the thread is interrputed Thread-0
Only t1.interuuption will not be enough .this need check the status of Thread.interrupted() in child thread.
I have a thread that calls the wait method and can only be awoken when the notify method called from some other class:
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
public void run() {
synchronized(this) {
for(int i=0;i<100;i++) {
total += i;
}
notify();
}
}
}
In the above code if the synchronized block in main, if the ThreadA does not execute first and instead the other synchronization block executing and completes to completion, then ThreadA executes its synchronized block and calls wait, what is going to happen and how it will be notified again?
If ThreadB gets through its synchronized block before ThreadA does, then ThreadA will block indefinitely on the call to wait. It won't somehow be notified that the other thread has already completed.
The problem is that you're trying to use wait and notify in ways that they are not designed to be used. Usually, wait and notify are used to have one thread wait until some condition is true, and then to have another thread signal that the condition may have become true. For example, they're often used as follows:
/* Producer */
synchronized (obj) {
/* Make resource available. */
obj.notify();
}
/* Consumer */
synchronized (obj) {
while (/* resource not available */)
obj.wait();
/* Consume the resource. */
}
The reason that the above code works is that it doesn't matter which thread runs first. If the producer thread creates a resource and no one is waiting on obj, then when the consumer runs it will enter the while loop, notice that the resource has been produced, and then skip the call to wait. It can then consume the resource. If, on the other hand, the consumer runs first, it will notice in the while loop that the resource is not yet available and will wait for some other object to notify it. The other thread can then run, produce the resource, and notify the consumer thread that the resource is available. Once the original thread is awoken, it will notice that the condition of the loop is no longer true and will consume the resource.
More generally, Java suggests that you always call wait in a loop because of spurious notifications in which a thread can wake up from a call to wait without ever being notified of anything. Using the above pattern can prevent this.
In your particular instance, if you want to ensure that ThreadB has finished running before ThreadA executes, you may want to use Thread.join(), which explicitly blocks the calling thread until some other thread executes. More generally, you may want to look into some of the other synchronization primitives provided by Java, as they often are much easier to use than wait and notify.
You could loop and wait until the total has been computed :
synchronized(b) {
while (total == 0) {
b.wait();
}
}
You could also use a higher-level abstraction like a CountDownLatch.
It is possible for ThreadB's run method to complete before you enter the synchronized block in ThreadA.main. In that situation, since the notify call has happened before you started waiting, ThreadA will block forever on the wait call.
A simple workaround would be to grab the lock on b in main before you start the second thread to ensure the wait happens first.
ThreadB b = new ThreadB();
synchronized(b) {
b.start();
...
b.wait();
}
You probably want to use a java.util.concurrent.Semaphore for this.
1) You need to add some flag that is used to communicate between the threads, so that B can signal to A when it is finished. A simple boolean variable is fine, as long as it is only read and written within the synchronized blocks.
synchronized(this) {
for(int i=0;i<100;i++) {
total += i;
}
isDone = true;
notify();
}
2) A needs to loop while waiting. So if your boolean variable was called isDone, and was set to true by threadB, then threadA should have some code like this:
synchronized(b) {
System.out.println("Waiting for b to complete...");
while( ! isDone ) b.wait();
}
In this particular case, there's actually no reason to have the synchronized block in A - since threadB doesn't do anything after it finishes running, and A doesn't do anything except wait for B, threadA could simply call b.join() to block until it finishes. I assume that your actual use case is more complex than this.
Why to make that complex ? Just use join() function of Thread.
ThreadB b = new ThreadB();
b.start();
b.join();
// now print b.total
do not synchronized(thread), don't do it, do not synchronized(thread).. repat: no synchronized(thread) :)
And if you need to wait for the thread 'b' to finish, use b.join(), now your code is free to hang in b.wait()
--
Hopefully the source below can grant you an insight while sync(thread)/notify() I consider bad practice. (cut-cut)
Enjoy
To proceeed below you make sure you have accepted Oracle's License aggreement, found there:
https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewLicense-Start?LicenseUUID=7HeJ_hCwhb4AAAEtmC8ADqmR&ProductUUID=pGqJ_hCwj_AAAAEtB8oADqmS&cnum=&evsref=&sln=
Java sources (incl), called in init(), effectively called by any java c-tor, since java 1.5
private static **synchronized int** nextThreadNum() {
return threadInitNumber++;
}
//join (the method w/ nanos only increase millis by one, if nanos>500000, millis==0 and nanos>0
public final **synchronized** void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
public **synchronized** void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
//stop1 is called after stop ensures proper priviledges
private final **synchronized** void stop1(Throwable th) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if ((this != Thread.currentThread()) ||
(!(th instanceof ThreadDeath))) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
// A zero status value corresponds to "NEW"
if (threadStatus != 0) {
resume(); // Wake up thread if it was suspended; no-op otherwise
stop0(th);
} else {
// Must do the null arg check that the VM would do with stop0
if (th == null) {
throw new NullPointerException();
}
// Remember this stop attempt for if/when start is used
stopBeforeStart = true;
throwableFromStop = th;
}
}