I have myThread.wait() that is in synchronzed(myThread) block. And I have Myrunner that implements runnable. I would like to tell notify() from myRunner, but it is not monitor object. Is it possible to get handle of myThread from myRunnable to make notify? Is there any other solution? Extend myRunnable from Thread and run it is not good for some reasons related on my code specific.
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(3000);
synchronized(this) {
System.out.println("notifying");
notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
Both threads should synchronize using the same object. Also, you should really not use an existing object to syncronize, but create a object to be used explicitly for synchronization, like
Object lock = new Object();
Also see https://www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reused
If the lock is to be used to interact with your thread, you can put it in the thread and provide a getter for anyone to use it.
To notify() a wait()ing thread you much have a reference to the object it is wait() on and you must be able to acquire a lock on it. I suggest you also change a state which notifying and you check that state change in a loop when wait()ing.
The only other option is to change the code of the waiting thread.
Related
I have been assigned an exercise from my uni professor that goes as follow:
"A fence object is an object that has a collection of objects, and can wait on any of those objects is signaled. There is an add(Object) method, which adds an object to the collection. There is also an await() method: this allows to wait on any object of the collection to be signaled. Whenever the add(Object) method is called while the await() method is active, the argument of the add is put in queue. Write the source code using the following interface: ".
public interface Fence {
public void await() throws InterruptedException;
public void add(Object o);
}
So, only when the same number of notify() and objects in queue (aka the number of add(Object) ) are called, the await() terminates and the object in the queue are finally added to the collection. <- this is something I got wrong and realized after writing my code
I did make the implementation as follow:
import java.util.LinkedList;
public class FenceImpl2 implements Fence{
private LinkedList<Object> collection;
private Object mutex; ;
static boolean iswaiting = false;
public FenceImpl2() {
this.collection = new LinkedList<Object>();
this.mutex = new Object();
}
#Override
public void await() throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
synchronized(mutex) {
mutex.wait();
iswaiting = true;
}
} catch (InterruptedException e) {
e.printStackTrace();
}}});
t1.start();
}
#Override
public void add(Object o) {
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized(mutex){
if(iswaiting == true) {
try {
mutex.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else {
collection.add(o);
}
}}});
t2.start();
}
public Object getList() throws InterruptedException {
synchronized(mutex){
System.out.println("Collection list: \n");
for(Object o : collection) {
System.out.println(o);
Thread.sleep(1000);
}
System.out.println("------- \n");
return collection;
}
}
public void notification() {
Thread thread = new Thread(()->{
synchronized(mutex){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mutex.notify();
}
});
thread.start();
}
public static void main(String[] args) throws InterruptedException {
FenceImpl2 f = new FenceImpl2();
Object o1 = 1;
Object o2 = 2;
Object o3 = 3;
Object o4 = 70;
f.add(o1);
System.out.println("Add 1");
f.add(o2);
System.out.println("Add 2");
f.add(o3);
System.out.println("Add 3");
f.await();
System.out.println("Await active ");
f.add(o4);
System.out.println("Aggiungo 70 - Shouldn't appear. Forced in queue");
f.getList();
f.notification();
System.out.println("Notify() sent - 70 should now appear in the collection");
f.getList();
}
}
After submitting it to my professor I have been told two things:
The synchronization is not correct: the await "unlocks" after the first notify and that shouldn't happen because it doesn't wait for the other (if any) objects that are in queue to be notified.
^Let me say I know how to fix that easily but
Although it's a minor mistake, the methods await, add and notification SHOULD NOT be done using asynchronous dedicated threads.
Here it finally comes my problem. How am I supposed to use wait() on a lock object and then notify() if I am not using dedicated threads?
I tried removing the threads but obviously as soon as I'm calling mutex.wait() the program locks and the code right after that calls the notification method is not reached.
Why did my professor tell me using threads is wrong?
How can I use a wait() and then call a notify() in two separate methods without having the program lock?
Here's an example of what I mean:
public class testw {
private Object mutex;
boolean condition = false;
public testw() {
this.mutex = new Object();
}
public void startWait() {
synchronized(mutex) {
try {
Thread.sleep(1000);
condition = true;
while(condition == true) {
System.out.println("Waiting!");
mutex.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void sendNotify() {
synchronized(mutex) {
try {
Thread.sleep(3000);
System.out.println("Notify!, not waiting anymore");
condition = false;
mutex.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
testw t = new testw();
t.startWait();
t.sendNotify();
}
Without using threads, when I startWait() is called the main thread goes in wait, but there's no way that sendNotify() to be called and the programs freezes. Is there a way to do this without using threads or am I missing something?
Thank you very much.
I have been told...Although it's a minor mistake, the methods await, add and notification SHOULD NOT be done using asynchronous dedicated threads.
The whole point of a method named await() is that it should not return until the event that the caller wants to wait for has happened.
Your await() method doesn't wait. It creates a new thread and then it immediately returns. The new thread waits for something, but after that it just dies without doing anything useful. The new thread might as well not exist at all.
Your add(o) method doesn't make a whole lot of sense either. I'm not even sure what you were trying to do with it, but I think you need to take a step back, and try to explain to the duck why you thought that either of those two methods should create a new thread.
How am I supposed to use wait() on a lock object and then notify() if I am not using dedicated threads?
The Oracle "Guarded Blocks" tutorial is an oldie but a goodie. If you work through it to the end, it should give you a pretty clear idea of how and why and when to use wait() and notify().
https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
I've an object that's created when the class is instantiated. I create a lock i-e; wait() on that object inside a background thread, however the app still gets unresponsive. My understanding of synchronization/locking is that if object.wait() is called in the main thread than it's equivalent to blocking the main thread however if it's called inside a background thread (even though the object upon which wait() is called in the main thread, shouldn't cause problems).
Can someone please help me out understanding this?
Example code:
class MyClass {
private final Object myLockObject = new Object();
public void connect() {
new Thread(new Runnable{
mSocket.connect();
myLockObject.wait(); // causing ANR
}).start();
}
private void socketConnectCallback() {
//upon callback
myLockObject.notifyAll();
}
}
class MyAndroidService extends Service {
public void onStartCommand() {
MyClass myClassObject = new MyClass();
myClassObject.connect();
//it immediately returns here even with the code written above.
}
}
First of all, this code will throw an IllegalMonitorStateException. This is because before calling object.wait(), you need to make sure that you are holding the object's monitor. One way to do this is to use:
synchronised(object) {
// this thread now owns the object's monitor
object.wait();
}
Further, the thread that calls for object.wait() relinquishes its ownership on that object's monitor and waits for some other thread to notify it. Once it gets the notification, it will wait until it reacquires the object's monitor (since some other thread might be having the ownership of that monitor even if the waiting thread got the notify signal). Then it continues normal execution.
In your case, the background thread should block, and the main thread should continue executing normally. Isn't this what you have mentioned is happening?
I don't know if this will help so much, but I can't comment so I want to get your attention to this code:
newThread(new Runnable {
mSocket.connect();
myLockObject.wait();
}).start();
This must be like:
(new Thread( new Runnable() {
public void run() {
try {
mSocket.connect(); // connect takes argument(s)
} catch (IOException e) {
// Catch the excpetion
}
try {
myLockObject.wait();
} catch (InterruptedException e) {
// Catch the excpetion
}
}
})).start();
and since Runnable is a functional interface you can use lambda expression instead of creating a new object.
Edit:
I think I figured out what do you want to do, if you want to make a thread that connects the socket and then wait to be notified and want it to acquire the intrinsic lock of the object myLockObject to prevent interleaving then you have to put the code you want to be executed by the thread in a guarded block:
private final void connectSocket() {
synchronized(myLockObject) {
try {
mSocket.connect(null);
} catch (IOException e) {
}
try {
myLockObject.wait();
} catch (InterruptedException e) {
}
}
}
and in the connect method just call connectSocket
public void connect() {
new Thread(new Runnable() {
public void run() {
connectSocket();
}
}).start();
}
I have 2 java class "LegacyDAO" and "NewDAO" implementing Runnable. In an another class "Test" we create one object of each LegacyDAOObj and NewDAOObj.
Class Test {
public static void main(String args[]) {
LegacyDAO legacyDAOObj= new LegacyDAO();
NewDAO newDAOObj= new NewDAO();
Thread legacyDBThread= new Thread(legacyDAOObj);
Thread newDBThread= new Thread(newDAOObj);
}
}
Is there any relation between legacyDBThread and newDBThread ?
If I want newDBThread to execute some code and then wait for legacyDBThread to finish and then continue running. How can this be achieved ?
wait() and notify() API is helpful here. you can share some objects in two class and use wait-notify on these shared objects to sync two thread.
You can use countdown latch. Create a count down latch with count one, pass it to legacyDAOObj. After the logic executed in legacyDAOObj, count down the latch. Till the logic is executed in legacyDAOObj, newDAOObj awaits.
If you just want to wait for a thread to end, use Thread#join(), it seems to be the easiest way to achieve what you want.
CountdownLatch will be your best bet. Your newDaoObj will continue in main thread once legacyDaoObj finishes.
public static void main(String[] args) {
CountDownLatch start =new CountDownlatch(1);
LegacyDAO legacyDAOObj= new LegacyDAO();
NewDAO newDAOObj= new NewDAO();
new Thread(new Worker(legacyDAOObj)).start();
try {
start.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
newDAOObj.doSomething();
}
public static class Worker implements Runnable{
LegacyDAO dao;
public Worker(LegacyDAO dao) {
this.dao = dao;
}
#Override
public void run() {
try {
start.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
dao.doSomething();
start.countDown();
}
}
I do not understand why Java throw exception from subject in this code. Could somebody explain me it?
class Wait implements Runnable
{
public void run() {
synchronized (Object.class) {
try {
while(true) {
System.out.println("Before wait()");
wait();
System.out.println("After wait()");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ObjectMethodInConcurency
{
public static void main(String[] args) {
Wait w = new Wait();
(new Thread(w)).start();
}
}
Use synchronized (this) { instead of synchronized (Object.class) in your class
EDIT
Reasoning behind the IllegalMonitorException in above code
In Java using synchronized keyword is a way to create and obtain a monitor object which will be used as lock to execute corresponding code block.
In the above code that monitor is "Object.class".
And wait() method tells the current thread to wait until it is notifyed and you have to invoke wait() on the monitor object which owns the lock.
So the way to invoke wait() method is like below otherwise you will get IllegalMonitorException.
synchronized(monitor){
monitor.wait();
}
So for your example you can either use "Object.class.wait()" or change the monitor to this since you are calling wait() method on the current instance
Supposed I have a class MyThread, which implements Runnable with a method dosomething():
class MyThread implements Runnable{
Object dosomething(Parameter p){ ... }
run(){...};
}
If I do:
main(){
MyThread my = new MyThread().run();
Object o = my.dosomething(p);
}
will dosomething be executed on myThread or in the main Thread?
How can I start the execution of dosomething on myThread from the main Thread and retrieve the returned Object?
main(){
MyThread my = new MyThread().run();
Object o = my.dosomething(p);
}
If you do that it won't compile: you're trying to assign the result of a void method, void run(), to an object of type MyThread.
Implementing runnable and calling run() will not cause the code to be executed in a separate thread unless you pass it to another thread (i.e. Tread t = new Thread(my);)
How can I start the execution of dosomething on myThread from the main Thread and retrieve the returned Object?
You do that by storing the result of doSomething() in a location where you can access it later.
class MyClass
{
public Object doSomething()
{
// return the object
return new Object();
}
}
class MyRunnable implements Runnable
{
private final MyClass _mc;
private final object _lock;
private final List<object> _results;
public MyRunnable(MyClass mc, List<object> results, object lock)
{
_mc = mc;
_lock = lock;
_results = results;
}
public void run()
{
synchronized(_lock)
{
_results.add(_mc.doSomething());
}
}
}
So now in main:
void main(){
MyClass mc = new MyClass();
List<object> results = new List<object>();
object lock = new object();
// Execute your thread and wait for it to complete
Thread t = new Thread(new MyRunnable(mc, results, lock ));
t.start();
t.join();
// Get the results
for(object result:results)
{
// do something with the result
}
}
This should give you an idea of what you're doing "wrong." A more realistic example would be if you spawn multiple threads, run them concurrently and then join on all of them until they all complete.
Sounds like you may want to consider Callables and Futures.
There's a decent explanation at http://www.vogella.de/articles/JavaConcurrency/article.html#futures
You can use delegate, for example.
new MyThread(callWhenFinishObject)
It'll be executed on the main thread, since it's that thread that calls the method. If you want dosomething to run in the separate thread, have it called within run() and store the result in a myThread field for later retrieval.
You might want to check class Future or other stuff in java.util.concurrent for some convenient way of waiting for the result to become available.
EDIT: if dosomething should only run until some condition is satisfied that must be flagged in the main thread, have run() block until the main thread somehow signals the other thread that it's okay to go on.
EDIT 2: here, someone confirm this is what's being asked:
package threadtest;
public class Main {
public static void main(final String[] args) {
final MyThread otherThread = new MyThread();
System.out.println("Main thread: I'm gonna start the other thread now...");
otherThread.start();
System.out.println("Main thread: there, hope it does well.");
try {
Thread.sleep(1000); //Lets main thread take a snooze...
} catch(InterruptedException ex) {
//whatever
}
System.out.println("Main thread: I'm gonna do some stuff in the meantime...");
try {
Thread.sleep(200); //Lets main thread take a snooze...
} catch(InterruptedException ex) {
//whatever
}
System.out.println("Main thread: maybe clean up the kitchen.");
try {
Thread.sleep(1000); //Lets main thread take a snooze...
} catch(InterruptedException ex) {
//whatever
}
System.out.println("Main thread: does other thread have something for me yet?");
if(otherThread.getResult() == null)
System.out.println("Main thread: nope, not yet.");
try {
Thread.sleep(500); //Lets main thread take a snooze...
} catch(InterruptedException ex) {
//whatever
}
System.out.println("Main thread: oh crap! I forgot to tell it that it may execute its method!");
otherThread.allowToExecute();
System.out.println("Main thread: phew... better keep checking now before it gets angry.");
while(otherThread.getResult() == null) {
try {
Thread.sleep(100); //Lets main thread take a snooze...
} catch(InterruptedException ex) {
//whatever
}
}
System.out.println("Main thread: there we go, it gave me a result. Rest in peace, other thread...");
}
private static class MyThread extends Thread {
private boolean mayExecuteDoSomething = false;
private Object result = null;
#Override
public void run() {
System.out.println("Other thread: whoa, someone started me!");
while(!mayExecuteDoSomething) {
try {
Thread.sleep(100); //I'm gonna sleep for a bit...
} catch(InterruptedException ex) {
//whatever
}
}
System.out.println("Other thread: alright, I'm allowed to execute my method!");
result = doSomething();
System.out.println("Other thread: there, did it. I'll just call it quits now.");
}
public void allowToExecute() {
mayExecuteDoSomething = true;
}
private Object doSomething() {
return new Object();
}
public Object getResult() {
return result;
}
}
}
This is a very crude approach to the issue. The basic concepts are there, though. In reality, you'd want to use stuff like Callable and Future for proper asynchronous computation.
That is not possible.
When you create a thread, it runs the code in run() and exits.
There is no way to inject code into a different thread; that would break the core execution model. (Within a thread, your code runs sequentially, with nothing in between)
If you want to, you can create a thread that listens for callback (Runnable instances) in a queue and executes them (like a message loop).
This is how the UI thread works.
Also, you aren't actually startign a thread; you need to write new Thread(someRunnable).start()