Reputation: 1266
Class Ui{
synchronized update()
{
do something
}
synchronized stop()
{
do something
}
}
Multiple threads are accessing the methods of the above class..
RunnableUI rm1 = new RunnableUI();
RunnableUI rm2 = new RunnableUI();
Thread rmt1 = new Thread(rm1);
Thread rmt2 = new Thread(rm2);
rmt1.start();
rmt2.start();
and Runnable UI Class is
class RunnableUI implements Runnable
{
public void run()
{
Ui u1 = new Ui();
u1.update(20);
u1.stop();
}
}
what i want to do is after stop method is called by first thread the second thread that would be waiting should start executing..
How do i do this..
Regards, Kaddy
Upvotes: 0
Views: 250
Reputation: 13374
@Kaddy, you have two problems with the code you posted:
Let me explain both. First, a really quick explanation of synchronized
. Consider this code:
class MyClass {
synchronized void myMethod() {
// do something
}
}
This is essentially shorthand for:
class MyClass {
void myMethod() {
synchronized (this) {
// do something
}
}
}
How synchronized
works is that if multiple threads try to sync on the same instance, then only one is allow inside the sync block at a time. When thread that did go inside leaves the block -- either through regular execution or because of exception -- then one of the remaining threads is allowed to enter its sync block. This goes on until no threads are trying to acquire a lock on that instance.
So to your first problem: each thread has its own instance of Ui. So the threads are sync'ing on different instances. You can fix that problem in two ways.
Either share one instance of Ui:
UI ui = new UI();
RunnableUI rm1 = new RunnableUI(ui);
RunnableUI rm2 = new RunnableUI(ui);
Or lock on something other than the UI instance:
class UI {
private static final Object LOCK = new Object();
public Object getLock() {
return LOCK;
}
public void update() {
synchronized (getLock()) {
// do something
}
}
...
}
To your second problem. You are not locking broadly enough. If you opt for a shared UI instance, try this:
class RunnableUI implements Runnable {
private final UI _ui;
RunnableUI(UI ui) {
_ui = ui;
}
public void run() {
synchronized (_ui) {
_ui.update(20);
_ui.stop();
}
}
}
If you opt for a shared lock, try this:
class RunnableUI implements Runnable {
public void run() {
UI ui = new UI();
synchronized (ui.getLock()) {
ui.update(20);
ui.stop();
}
}
}
Upvotes: 0
Reputation: 19131
Use an ExecutorService
:
RunnableUI rm1 = new RunnableUI();
RunnableUI rm2 = new RunnableUI();
ExecutorService processingThread = Executors.newFixedThreadPool(1);
processingThread.submit(rm1);
processingThread.submit(rm2);
processingThread.shutdown();
The first Runnable
will be invoked and keep running until somethings calls stop or the runnable finishes. As soon as that happens, the next Runnable
will be started, etc.
With this you can chain any number of runnables, reconfigure the service to use multiple threads to execute in parallel, etc. It's quite flexible.
Edit: I just realized that based on your description you do not want to wait for the first runnable to stop. If that is true, then this does not quite hit the mark, but I will leave it anyway.
Upvotes: 1
Reputation: 26291
I think what you want is a Semaphore. A semaphore maintains a fixed number of permits (1 in your case). You acquire
the permit in update
and release
it in stop
. If you need, I'll re-edit to add a code example.
Upvotes: 1
Reputation: 5849
You want the threads to be executed in sequence?
It doesn't really make sense but in that case you should insert a "rmt1.join();" (and necessary exception handling) between the two start calls.
Upvotes: 1