user4045893
user4045893

Reputation:

Java: calling join() multiple times on same thread?

I have threads A, B and C. I'm starting A and B simultaneously and thread C will execute it's logic after A and B end. I also want to do other operations after A ends and different operations after thread B ends.

So I designed it this way:

final Thread a = new Thread() {
    @Override
    public void run() {
        // do something
    }
};

final Thread b = new Thread() {
    @Override
    public void run() {
        // do something
    }
};

AbstractAction x = new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        a.start();
        try {
            a.join();
        } catch (InterruptedException e1) {
        }

        // do some other things
    }
};

AbstractAction y = new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        b.start();
        try {
            b.join();
        } catch (InterruptedException e1) {
        }

        // do some more different things
    }
};

Thread c = new Thread() {
    @Override
    public void run() {
        try {
            a.join();
            b.join();
        } catch (InterruptedException e) {
        }

        // do things after a and b ends
    }
};

I'm worried that I'm doing something wrong here, as I couldn't find any tips about calling join() multiple times on same thread.

On the other hand, I have no idea how can I achieve what I wand in other way. I could probably just use

while (a.isAlive() || b.isAlive()) {
    // do nothing
}
// do things after a and b ends

but for me it looks worse.

----- UPDATE 1 -----

If you asking why at all do such things...

There are two buttons b1 and b2.

x.performAction() shows indicator on b1 while in the background I'm loading data from DB (it's done in Thread a). y.performAction() makes similar thing for b2 but loads different portion of data (Thread b).

Putting start() and join() in actionPerformed() causes showing indicator as long as data is loading. When data loading is finished, indicator disappears.

There is also other action. Before data loading is finished, button is disabled (user can't click it).

The point is to enable both buttons (letting the user to click them) only after both portions of data is loaded from DB. The point is also to allow showing indicators separately - if Thread a finishes before Thread b, there is no point for showing indicator on button b1.

Upvotes: 1

Views: 2478

Answers (3)

OldCurmudgeon
OldCurmudgeon

Reputation: 65811

See the JavaDoc on join()

... uses a loop of this.wait calls conditioned on this.isAlive.

so it is safe to call join as many times as you like - a dead thread will always have false for isAlive.

It is also not possible to resurrect a thread.

It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.

Upvotes: 2

06needhamt
06needhamt

Reputation: 1605

It is safe to join multiple times on a thread

Also i noticed something not quite right if you want this code to do nothing while BOTH threads are alive why not just

while (!a.isAlive() && !b.isAlive()) {
    // do things
    break;
}

That just makes more sense to me than creating a loop to do nothing

EDIT: add a break so the loop with stop after executing once

Upvotes: 0

Marko Topolnik
Marko Topolnik

Reputation: 200158

Consider what can happen with this code:

a.join();
b.join();
proceed();
  1. Both threads may be dead—proceed immediately;
  2. a dead, b alive: block on second line until b dead;
  3. a alive, b dead: block on first line until a dead;
  4. both alive: block on first line until a dead, then block as needed until b dead.

All four cases share the following invariant:

proceed() is reached as soon as, but no sooner than, both a and b are dead.

Upvotes: 3

Related Questions