Threads, waiting for last one to finish

R

Roedy Green

I have 25 threads that start at once. I need to wait until the last
one completes. Is there a better way to handle that than using a
ThreadPoolExecutor which seems overkill.
 
M

markspace

I have 25 threads that start at once. I need to wait until the last
one completes. Is there a better way to handle that than using a
ThreadPoolExecutor which seems overkill.

The Executors class has convenience methods to make thread pools easier
to use.

ExecutorService es = Executors.newFixedThreadPool( 25 );
// submit jobs here
es.shutdown();

The shutdown() will wait for all jobs to finish. I don't think you can
get easier than that. It's two lines of code!
 
A

Arne Vajhøj

Oops, sorry, it's awaitTermination() that you want, not shutdown().

If the Java docs are to be believed he actually wants both.

<quote>
Blocks until all tasks have completed execution after a shutdown
request, or
</quote>

Arne
 
K

Knute Johnson

I have 25 threads that start at once. I need to wait until the last
one completes. Is there a better way to handle that than using a
ThreadPoolExecutor which seems overkill.

You can always join() them.
 
A

Arved Sandstrom

I have 25 threads that start at once. I need to wait until the last
one completes. Is there a better way to handle that than using a
ThreadPoolExecutor which seems overkill.
Any reason why you couldn't use CyclicBarrier?

AHS
 
K

Kevin McMurtrie

markspace said:
The Executors class has convenience methods to make thread pools easier
to use.

ExecutorService es = Executors.newFixedThreadPool( 25 );
// submit jobs here
es.shutdown();

The shutdown() will wait for all jobs to finish. I don't think you can
get easier than that. It's two lines of code!

The Executor classes are horribly buggy. Pool size adjustment, idle
timeouts, and shutdown sequences do NOT work. Some of the features are
impossible to implement efficiently so Sun instead chose to implement
them incorrectly.

For an Executor, it would be more correct to iterate through all the
Future or Callable objects returned and ask for their result.
 
R

Roedy Green

Any reason why you couldn't use CyclicBarrier?

There are a few things that puzzle. What goes in the unshown
waitUntilDone? just an await? I suppose the mother thread too counts
as one of the "parties".

Why does CyclicBarrier have a Runnable? Would it not be simpler to
have the mother thread invoke a Runnable after the await? or just
execute the cleanup code on the same thread?

With CyclicBarrier, you must know the precise number of threads ahead
of time that will wait. In my case I have an upper bound. Sometimes
there is nothing to do for a given thread, and I don't even start it.
To use CyclicBarrier I would need a pre-sweep to get the precise
count.

In my case, one of the threads, the one that probes amazon.cn takes
quite a bit longer than the others. The way it is now, all the
threads but one shut down early and let the last thread have all the
resources. With CyclicBarrier they would all be hanging around to the
last minute.

Thank you for bringing this option up. I tend use to overuse the first
tool I encounter out of learning curve fear.
 
S

Sebastian

Am 11.01.2013 22:56, schrieb Roedy Green:
I have 25 threads that start at once. I need to wait until the last
one completes. Is there a better way to handle that than using a
ThreadPoolExecutor which seems overkill.

You could use a Phaser, like so:

final Phaser phaser = new Phaser(1);
for(int i=0; i < taskCount; i++) {
phaser.register();
executor.execute(new Runnable() {
public void run() {
try {
// do sth
);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
phaser.arrive();
}
});
}
phaser.arriveAndAwaitAdvance();


-- Sebastian
 
A

Arved Sandstrom

There are a few things that puzzle. What goes in the unshown
waitUntilDone? just an await? I suppose the mother thread too counts
as one of the "parties".

Why does CyclicBarrier have a Runnable? Would it not be simpler to
have the mother thread invoke a Runnable after the await? or just
execute the cleanup code on the same thread?

With CyclicBarrier, you must know the precise number of threads ahead
of time that will wait. In my case I have an upper bound. Sometimes
there is nothing to do for a given thread, and I don't even start it.
To use CyclicBarrier I would need a pre-sweep to get the precise
count.

In my case, one of the threads, the one that probes amazon.cn takes
quite a bit longer than the others. The way it is now, all the
threads but one shut down early and let the last thread have all the
resources. With CyclicBarrier they would all be hanging around to the
last minute.

Thank you for bringing this option up. I tend use to overuse the first
tool I encounter out of learning curve fear.
It's this option and also its close cousin the CountdownLatch - useful
synchronization constructs to be aware of.

I'll refer you to JCIP for a detailed exposition of the details between
CountdownLatch and CyclicBarrier - the key difference is that the latch
is waiting for an event (the latch count becoming 0 through invocations
of countDown()) while the barrier waits on other threads (these threads
arriving at the barrier when they call await()).

In either case, yes, you need to supply the number of threads involved.
That's to be expected. I have difficulty seeing how you wouldn't be able
to figure out how many threads you propose to start.

As for the Runnable for CyclicBarrier, you want to read the Javadoc
carefully. The barrier is going to run that *after* all threads arrive,
but *before* they are released - you're welcome to try and implement
that yourself.

As for threads taking different times, and "hanging around", I don't see
the problem. If each individual thread does resource cleanup - like
connections - before calling await(), what is the issue with a thread
doing basically nothing?

AHS
 
R

Robert Klemme

You can always join() them.

I am surprised that this got just one mention so far. In absence of
Executor (which has some issues, as has been mentioned) this is the most
straightforward way to do it.

// untested and from memory
final Thread[] threads = new Thread[15];

for ( int i = 0; i < threads.length; ++i ) {
final Thread th = new Thread(...);
th.start();
threads = th;
}

for ( final Thread th : threads ) {
th.join();
}

Kind regards

robert
 
R

Roedy Green

As for threads taking different times, and "hanging around", I don't see
the problem. If each individual thread does resource cleanup - like
connections - before calling await(), what is the issue with a thread
doing basically nothing?

does not a thread have 1 MB + overhead just for existing?
 
A

Arne Vajhøj

does not a thread have 1 MB + overhead just for existing?

Yes, no, it depends.

It is implementation dependent so it can and do differ between
different vendors and platforms.

Some may provide an option for changing the default.

I have once read that SUN/Oracle Java on Windows and Linux uses
320 KB and 1024KB as default on 32 and 64 bit respectively.

SUN/Oracle Java do provide the -Xss option to change the
default.

Arne
 
A

Arne Vajhøj

The Executor classes are horribly buggy. Pool size adjustment, idle
timeouts, and shutdown sequences do NOT work. Some of the features are
impossible to implement efficiently so Sun instead chose to implement
them incorrectly.

For an Executor, it would be more correct to iterate through all the
Future or Callable objects returned and ask for their result.


Can you be more specific about when shutdown and await does
not work?

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,233
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top