Kaddy
Kaddy

Reputation: 1266

Java Thread related question

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

Answers (4)

Dilum Ranatunga
Dilum Ranatunga

Reputation: 13374

@Kaddy, you have two problems with the code you posted:

  1. You have multiple instances of UI, and
  2. Your locking is per-method, but it appears you want to lock across methods.

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

SingleShot
SingleShot

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

Kathy Van Stone
Kathy Van Stone

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

Fredrik
Fredrik

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

Related Questions