The situation is like this, methodB() is called again and again when the app is running. When methodC() is called, methodB() will pause until methodC() is done. When methodA() is called, it will pause until methodB() done for three times but skip "Code X".
I've tried to add locker2, lock2 and threadLocker2() to do the pause of methodA(), but it didn't work as methodB() also pause. Can anyone give me some suggestions how can I do this?
private final Object locker = new Object();
private boolean lock = false;
public void methodA() {
//Lock until methodB() run three times
//Do something
}
public void methodB() { //A thread called again and again
//Do something
threadLock();
//Code X
}
public void methodC() {
lock true;
//Do something
lock = false;
synchronized (locker) { locker.notify(); }
}
private void threadLock() {
synchronized (locker) {
while (lock) {
try {
locker.wait();
} catch (InterruptedException e) {}
}
}
}
I would use an atomic boolean (or integer) or a volatile boolean for that.
This is the shared atomic / volatile boolean:
private AtomicBoolean secondMethodIsDone = new AtomicBoolean(false);
void firstMethod() {
methodInOtherThread();
while(!secondMethodIsDone.get()) {
//thread sleep waiting...
}
// do your things when second is done
}
This happens in another thread:
void methodInOtherThread() {
// do your stuff
// whenever is done:
secondMethodIsDone.set(true);
}
This should do it.
Related
i want to write own simple semaphore and done it as follows:
class Semaphore {
private boolean done;
private final Object lock = new Object();
public Semaphore(boolean done){ this.done = done;}
public void acquire() throws InterruptedException {
synchronized (lock) {
while (!done)
lock.wait();
done = false;
}
}
public void release() {
synchronized (lock) {
done = true;
lock.notify();
}
}
}
it works fine. But if i replace synchronized (lock) with synchronize (this) it begins to throw IllegalMonitorStateException. Why so?
As #Alexei Kaigorodov mentioned in comment, when you replace synchronized (lock) with synchronize (this). Then, you need to also replace lock to this in your code.
As this indicate to current object which is different than lock object.
Now, you replaced synchronized (lock) with synchronize (this) which means now you are trying to acquire lock on current object but you were waiting on object of Object class.
This works absolutely fine :
public void acquire() throws InterruptedException {
synchronized (this) {
while (!done)
this.wait();
done = false;
}
}
public void release() {
synchronized (this) {
done = true;
this.notify();
}
}
Let's say we have an infinite loop, and we want to put it to sleep for a while, and then resume it. Instead of having a set time, we resume it when we press a key.
For example, in Java we could have:
while(true){
doSomething();
}
Now, we could make this interruptable in many ways. We want to interrupt it on a key press, so we will have:
boolean running = true;
...
this.addKeyListener(this);
...
#override
public void keyPressed(KeyEvent e){
running = false;
}
And then run a method (let's say run), which contains:
while(running){
doSomething();
}
But then we'd meet one problem: resuming.
So we take the keyPressed method, and change it's body to:
running = !running;
if(running){
run();
}
There is just one problem here: the KeyListener won't do anything until the run method is finished. I've tried using threads, where we would have:
private class Runner implements Runnable {
#Override
public void run() {
while (running) {
doSomething();
}
}
}
and in keyPressed:
if(running){
runner.wait();
}else{
runner.notify();
runner.run();
}
running = !running;
but in my actual code the doSomething method is code that can't be interrupted (because it handles output to the screen), so thread.wait() can never be called (it will throw exceptions all the time and not actually wait).
So then, to summarize: How does one stop and resume looping something at will using key input in Java?
wait and notify are intended to be called from different threads. As the name implies, wait should be called in the thread which is paused and waiting to be notified that a condition has changed:
private final Object keyPressMonitor = new Object();
private boolean running = true;
private Runnable gameLoop = new Runnable() {
#Override
public void run() {
try {
synchronized (keyPressMonitor) {
while (true) {
while (!running) {
keyPressMonitor.wait();
}
doSomething();
}
}
} catch (InterruptedException e) {
logger.log(Level.INFO,
"Interrupted; cleaning up and exiting.", e);
}
}
};
The other thread, presumably the AWT Event Dispatch Thread which is where your KeyListener (or Action invoked by an ActionMap/InputMap binding) is called, would notify the looping thread that the proper key has been pressed or released:
public void keyPressed(KeyEvent event) {
if (event.getKeyCode() == theKeyICareAbout) {
synchronized (keyPressMonitor) {
running = true;
keyPressMonitor.notifyAll();
}
}
}
public void keyReleased(KeyEvent event) {
if (event.getKeyCode() == theKeyICareAbout) {
synchronized (keyPressMonitor) {
running = false;
keyPressMonitor.notifyAll();
}
}
}
You can use Semaphore for these purposes:
private static class Runner implements Runnable {
private final AtomicInteger permits = new AtomicInteger(0);
private final Semaphore semaphore = new Semaphore(1, true);
private volatile boolean running;
public void putToSleep() {
semaphore.acquireUninterruptibly();
}
public void resume() {
semaphore.release(permits.getAndSet(0));
}
#Override
public void run() {
while (running) {
semaphore.acquireUninterruptibly(Integer.MAX_VALUE);
semaphore.release(Integer.MAX_VALUE);
doSomething();
}
}
private void doSomething() {
//...
}
}
I have methodA and methodB and methodSync in my java program.
I want that when a thread is inside methodSync other threads don't run the methodA and methodB and wait for methodSync to end. But methodA and methodB can run simultaneously.
If I want to sync 3 methods with each other I can use this code:
private static final Object LOCK = new Object();
public static void methodA() {
synchronized (LOCK) {
//Do Job
}
}
public static void methodB() {
synchronized (LOCK) {
//Do Job
}
}
public static void methodSync() {
synchronized (LOCK) {
//Do Job
}
}
But this is not a solution for me because I want to run methodA and methodB simultaneously.
private static final Object A = new Object();
private static final Object B = new Object();
public static void methodA() {
synchronized (A) {
//Do Job
}
}
public static void methodB() {
synchronized (B) {
//Do Job
}
}
public static void methodSync() {
synchronized (A) {
synchronized (B) {
//Do Job
}
}
}
I guess that will work. Good luck.
P.S. You can replace synchronized with ReadWriteLock (acquiring the read lock in methods A & B and the write lock in methodSync. If that's worth doing is if you want two callers in methodA at the same time.
Suppose there is the following code:
class MyClass {
synchronized void myMethod1() {
//code
}
synchronized void myMethod2() {
//code
}
}
Now suppose myMethod1() and myMethod2() access distinct data; now if there are two threads, thread A calling only myMethod1() and thread B calling only myMethod2().
If thread A is executing myMethod1(), will thread B block waiting on myMethod2() even if they don't access the same data and there is no reason for this? As far as I know, synchronized methods use the monitor of this object for instance methods and that of MyClass.class object for static functions.
Your understanding of the situation is correct.
The typical solution is to have separate dedicated lock objects for the resources in question.
class MyClass {
private final Lock lock1 = new ReentrantLock();
private final Lock lock2 = new ReentrantLock();
void myMethod1() {
lock1.lock();
try {
//code
} finally {
lock1.unlock();
}
}
void myMethod2() {
lock2.lock();
try {
//code
} finally {
lock2.unlock();
}
}
}
You are correct in all your suppositions. In the case where no data is in common then there is no reason to synchronize at the method level.
The sychronized method will lock on the object itself. So each method will have to wait for the other to finish its access to release the object. If your methods are truly accessing distinct data you can do something like this:
class MyClass {
private static Object mLock1 = new Object();
private static Object mLock2 = new Object();
void myMethod1() {
synchronized(mLock1) {
//code
}
}
void myMethod2() {
synchronized(mLock2) {
//code
}
}
}
And you can then access them independently.
edit: You can essentially think of synchronized methods as being equivalent to this:
void myMethod1() {
synchronized(this) {
//your code
}
}
Shown like this it is pretty clear why two synchronized methods block each other because they have to wait for the lock on this to free.
Yes, declaring both methods as synchronized will make them block each other, even if they access different data elements.
To avoid this, you can use a more fine grained locks. E.g.:
class MyClass {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
void myMethod1() {
synchronized (lock1) {
//code
}
}
void myMethod2() {
synchronized (lock2) {
//code
}
}
You can use different monitors for myMethod1 and myMethod2 as follows:
class MyClass {
Object monitor1 = new Object();
Object monitor2 = new Object();
void myMethod1() {
synchornized(monitor1) {
//code
}
}
void myMethod2() {
synchronized(monitor2) {
//code
}
}
}
I have 3 threads (A, B, C) that i just can't make them work how i want them to.
ALL these 3 threads share a reference to the same object - K.
What i'm trying to do, is to start all 3 up, then at some point in time when thread A arrives in a certain state, pause threads B and C, until A executes some method work() and when work finishes, resume B and C.
Now what i have in my code:
Thread A has reference to both B and C.
B and C have a method pause() { synchronized(K) { k.wait; }}
When A arrives in that certain state, i call FROM A's run() method: B.pause(), C.pause().
Now what i'm expecting is that Threads B and C will waiT until someone makes a: k.notifyAll(), BUT instead Thread A stops. Is this normal in java ?
Code:
class A implements Runnable {
private K k;
private B b;
private C c;
void run() {
while(something) {
//do something
b.pause();
c.pause();
// !!! here this thread will freeze and doSomething2 wont get executed.
// what i want is to pause B, C, doSomething2 to get executed and then resume B and C
//do something2
synchronized(k) {
k.notifyAll();
}
}
}
}
class B implements Runnable {
private K k;
void run() {
while(something) {
//dome something
}
}
}
public pause() {
synchronized(k) { k.wait();}
}
}
class C implements Runnable {
private K k;
void run() {
while(something) {
//dome something
}
}
}
public pause() {
synchronized(k) { k.wait();}
}
}
You can use a CylcicBarrier to implement this.
CyclicBarrier barrier = new CyclicBarrier();
public void run() {
new Thread(new A(barrier)).start();
new Thread(new B(barrier)).start();
barrier.await(); // Waits until all threads have called await()
// Do something
}
public void A implements Runnable {
private CyclicBarrier barrier;
public A(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
barrier.await();
// Do something.
}
}
public void B implements Runnable {
private CyclicBarrier barrier;
public B(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
barrier.await();
// Do something.
}
}
When you call B.pause(), it is executed in the local thread, not in the thread where you called run method of B.
There are some deprecated methods on the Thread class to do that but they are dangerous, see here:
http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
Are you sure that you call b.pause() but declare B.sleep() ?
Would be nice to see threads construction/start code.
You know that you are using 3 diferent objects (monitors) A.k,B.k,C.k ?
So when B "paused" it synchronized on their own monitor (B.k) that should be free anyway.
Your threads do not "communicate" in any way.
Remove the calls to b.pause() and c.pause() from A.run() and call them from their own run methods.
Unless I am misunderstanding your homework assignment, what I think you need to do is learn how to interrupt a thread. B and C are interruptable threads that need to handle the interrupt in such a way that they will not resume until they have been told it is OK. It could look something like this:
while(true)
{
try
{
Thread.sleep(100);
System.out.println("Thread is working normally...");
}
catch(InterruptedException e)
{
System.out.println("Thread has been interrupted, will wait till A is done...");
try
{
synchronized(monitor)
{
monitor.wait();
}
}
catch(InterruptedException e2)
{
// whatever...
}
}
}
So object A running in its own thread will have references to two other threads. Object A will have access to a shared monitor object that the runnables in the two other threads also have access to (I called it monitor). When A interrupts the other threads their runnables will then call wait() on the monitor. When A is done it will call notifyAll() on the monitor. NOTE you should clear the interrupt flag in the other threads too, but I leave that to you to figure out - its easy :)
I don't normally help with homework in this detail, but I think you are using the wrong approach anyway, so I don't see the harm in helping you do something you almost certainly shouldn't be doing :)
class A implements Runnable {
private K k;
private B b;
private C c;
void run() {
while(something) {
//do something
b.pause();
c.pause();
// !!! here this thread will freeze and doSomething2 wont get executed.
// what i want is to pause B, C, doSomething2 to get executed and then resume B and C
//do something2
synchronized(k) {
k.notifyAll();
}
}
}
}
class B implements Runnable {
private K k;
volatile boolean isPaused = false;
void run() {
while(something) {
if (isPaused) {
synchronized(k) { k.wait();}
isPaused = false;
}
//dome something
}
}
public pause() {
isPaused = true;
}
}
class C implements Runnable {
private K k;
volatile boolean isPaused = false;
void run() {
while(something) {
if (isPaused) {
synchronized(k) {
k.wait();
}
isPaused = false;
}
//dome something
}
}
public pause() {
isPaused = true;
}
}
I'm guessing that what you really want to do though is unconditionally call wait in on k in B and C and then always call notifyAll in A