I have some experience with threading in java, but I am wondering...
What's the best practise to store multiple threads where I can access them both individually and as a group?
My own solution is to create a threadArray
class but naturally I would prefer a native class that is much more reliable.
Thanks in advance!
edit
Apparently the functionality is of great importance of the best method. Well, I'll give an example:
I've got an application that basically searches through a lot of information at the same time hence I'm using threads. The threads however each need to perform just a part of the entire operation so I wish to add additional parameters to specify a range.
When a thread finishes it's specific search it can just stop naturally. When a thread finds a result however, I wish to stop all threads and retrieve that result.
Does that help?
I'd use an ExecutorService
to manage my threads as a pool and put the Future
s I am given when adding my Threads
to the pool in some form of Collection
.
In this way you can manage all of the threads as one unit via the Executor and track individual threads through their Future
.
Edit in response to yours
You can use the shutdownNow
method of the ExecutorService
to abort all running threads.
Example (not a solution to your problem but covers most benefits of using Executors):
// Thread pool for the collectors.
ExecutorService threads = Executors.newFixedThreadPool(MAX_THREADS);
...
// Futures of all collectors running in the pool.
ConcurrentLinkedQueue<Future> collectors = new ConcurrentLinkedQueue<Future>();
...
// Make my Callable.
Callable<Void> c = new FileListCollector(path, recurse, filter);
// Start it up and keep track of it so we can find out when it has finished.
collectors.add(threads.submit(c));
...
// Called when nothing in queue.
private void checkForFinished() {
// Count the running threads.
int runningThreads = 0;
try {
// Track dead ones to remove.
List<Future> deadThreads = new LinkedList<Future>();
// Walk all collectors.
for (Future f : collectors) {
// I've seen f being null once. No idea how.
if (f != null) {
// If it's not done then it's running.
if (!f.isDone()) {
// Count it.
runningThreads += 1;
} else {
// Mark for deletion.
deadThreads.add(f);
}
}
}
// Clear dead threads - just to be tidy.
collectors.removeAll(deadThreads);
} catch (ConcurrentModificationException cme) {
// Probably a new thread has been started while I was checking!
// Therefore almost certainly NOT all finished.
runningThreads += 1;
}
// If no threads are left, we're done.
if (runningThreads == 0) {
// Finished! Close everything down.
close();
}
}
// Close down the whole system.
public void close() {
// Use the fileQueue state to indicate closed.
if (!fileQueue.isClosed()) {
// Close the queue ... unblocking all collectors (I hope).
fileQueue.close();
// Shut them down agressively as this may be called by user prematurely as well as by me.
threads.shutdownNow();
// Wait until all is done.
boolean terminated = false;
do {
try {
// Wait up to 1 second for termination.
terminated = threads.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
// Ignore the interrupt! If I exit here we will probably leak.
}
} while (!terminated);
log("! All done");
}
}
I would just use a thread pool, and more specifically a thread pool executor. That would maintain a cache of threads for you to use, although you won't be able to access specific threads on demand.
I often simply place Thread
references inside standard containers.
The choice of container depends on what exactly you want to do with the objects.
Synchronize your writes, and you're good. There isn't much more to it unless you're doing something special or unusual. You can do this by modifying your code to only allow one thread the ability to write at a time, or you can have just one thread do all the writing.
A "native" class won't offer you more reliability necessarily, if you cover your bases with multiple write access.
I'm not sure how old this trail is, but covers the basics synchronization, multiple thread access, and a few other things.
Why not use one of Java's Collection Framework?
I have used a Map
to store threads, the purpose was for an online game so I stored the reference to client threads in a map with the character name (which was unique) as the key to the thread.
Just choose the collection that best suits your needs.
Along with this you can use methods in the Collections
class to create synchronized versions of the Collections as needed.