For leaning purpose i am trying to implement my own thread pool in java. Below is what i have implemented. I have few questions about this implementation:
Although i am using BlockingQueue like built in java Executors expect us to provide Runnable objects (through execute method). But in my case i feel like i can create any object instead of Runnable. So then why does Java executors expect Runnable, i tried looking into the source code but could not figure it out yet.
Is there anything else wrong with this primitive implementation ?
Please find the code.
public class CustomThreadPool {
private final BlockingQueue<Runnable> blockingQueue;
private final Worker[] workers;
public CustomThreadPool(final int numOfThreads) {
blockingQueue = new LinkedBlockingQueue<>();
workers = new Worker[numOfThreads];
for (int i = 0; i < numOfThreads; i++) {
workers[i] = new Worker();
workers[i].start();
}
}
public void execute(final Runnable task) {
blockingQueue.add(task);
}
public void shutdownImmediately() {
for (int i = 0; i < workers.length; i++) {
workers[i].shutdownSignal = true;
workers[i] = null;
}
}
private class Worker extends Thread {
private Runnable taskToPerform = null;
boolean shutdownSignal = false;
#Override
public void run() {
while(true && !shutdownSignal) {
taskToPerform = blockingQueue.poll();
if (taskToPerform != null) {
taskToPerform.run();
}
if(shutdownSignal) {
break;
}
}
}
}
public static void main(String[] args) throws Exception {
final CustomThreadPool threadPool = new CustomThreadPool(5);
for (int i = 0; i < 20; i++) {
threadPool.execute(() -> System.out.println(Thread.currentThread().getName()));
}
Thread.sleep(1*1000);
threadPool.shutdownImmediately();
}
}
Executor expects Runnable or Callable because it will call run or call method of these interfaces when it is running the tasks you submitted.
In Your implementation You don't use blocking aspects of BlockingQueue. Your thread pool threads will spin constantly(take cpu time) on Your while(true && !shutdownSignal) loop when there is no task exists in Your queue. Because poll() method is not blocking. And this not something You would want when implementing a thread pool.
You should use one of the blocking methods instead of poll().
You can use poll(long timeout,TimeUnit unit) method which takes time out parameter. In this case if You call Your shutdownImmediately method while any thread pool thread waiting on this call. They will wait for the time out duration and poll will return null to them They will see shutdownSignal is being set and get out of the loop. You can also call interrupt method If You don't want them to wait for the timeout.
// in run method
try {
taskToPerform = blockingQueue.poll(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
break; // this thread is interrupted. Time to leave this loop
}
// in shutdownImmediately method
workers[i].shutdownSignal = true;
// If You don't call interrupt, Threads will wait at max 5 sec for this case.
workers[i].interrupt();
workers[i] = null;
Or You can use take() method which blocks when there is nothing on the queue. But in this case You have to interrupt the threads that might be waiting on the take method call when You call Your shutdownImmediately method. Otherwise they will stuck at the take() call.
// in run method
try {
taskToPerform = blockingQueue.take();
} catch (InterruptedException e) {
break; // this thread is interrupted. Time to leave this loop
}
// in shutdownImmediately method
workers[i].shutdownSignal = true;
workers[i].interrupt(); // this is crucial for this case
workers[i] = null;
Related
I am creating a fixed-size thread pool with 10 threads as follows:
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < poolSize; ++i) {
executorService.execute(factory.get());
}
Now, after spawning 10 threads, a runnable is being executed by each of them. Runnable here is provided by factory.get()
Now, I wanted to do a thing that as soon as a thread gets shutdown, i.e. it has completed a task, it picks another runnable again and start running it. So, basically check for all 10 threads state and execute a runnable again if the thread is shutdown.
I know I can do something like, in which I can call the executorService shutdown() method as follows to do that:
while (!executorService.isShutdown()) {
try {
executorService.execute(factory.get());
} catch (RejectedExecutionException e) {
if (!executorService.isShutdown())
log.warn("task submission rejected");
}
}
But in this approach, issue is that I am keep on calling the execute function which would increase LinkedBlockingQueue and won't serve my purpose.
If I can somehow check the Threads state, that would be good because then, it would avoid the overhead of going back to get more work from the executor service.
Please suggest how can I do that in code.
You can use a bounded executor. The following is code by Brian Goetz from jcip
/**
* BoundedExecutor
* <p/>
* Using a Semaphore to throttle task submission
*
* #author Brian Goetz and Tim Peierls
*/
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command)
throws InterruptedException {
semaphore.acquire();
try {
exec.execute(new Runnable() {
public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
}
}
}
Then just create and use it:
ExecutorService executorService = Executors.newFixedThreadPool(10);
BoundedExecutor boundedExecutor = new BoundedExecutor(executorService,10);
while (!executorService.isShutdown()) {
try {
boundedExecutor.submitTask(factory.get());
} catch (InterruptedException e) {
}
}
This way you will always have 10 threads running, new tasks will only be submitted after the old ones will complete and you can stop the execution by shutting down the executor.
Why use a thread pool if you're going to run 10 threads continually? Just start 10 threads yourself.
Why have a "controller" thread on top of the 10 worker threads? Just let each thread ask for the next task to execute.
The following assumes that factory.get() is thread-safe.
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (;;) {
Runnable r = factory.get(); // <-- must be thread-safe
if (r == null)
break; // stop thread if no more tasks to execute
try {
r.run();
} catch (Exception e) {
// log exception here
}
}
}).start();
}
If needed, save the 10 thread objects in an array.
If you want to be able to shutdown the threads without having factory.get() returning null, add a volatile boolean, and check it in the loop.
I'm learning Java threads and want my code to output threads 0-9 in sequential order. I used the synchronized keyword but I don't get the results I expect.
What should I do to correct my code?
public class MyThread extends Thread {
private static final int threadMax = 10;
private static int runCount = 0;
public void printThread() {
synchronized (this) {
while (runCount++ < 100) {
System.out.println(runCount + ": " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void run() {
printThread();
}
public static void main(String[] args) {
for (int i = 0; i < threadMax; i++) {
new MyThread().start();
}
}
}
It is not working as every time you are creating new MyThread object and you are synchronized over that new object. So, every Thread you created will get a lock on the diffrent object. So, you should pass a common object to take the lock like below.
class MyThread extends Thread {
private static int runCount = 0;
Object lock;
public MyThread(Object lock) {
this.lock = lock;
}
public void printThread() {
synchronized (lock) {
// your code here
}
}
//.........
}
And then call it like :
Object lock = new Object();
for (int i = 0; i < threadMax; i++) {
new MyThread(lock).start();
}
However, the above program will not ensure you that it will run in sequence. There are several ways to do that. You can use wait() and notify() to achieve your goal. Refer the below example :
public void printThread() {
while (runCount < 90) {
synchronized (lock) {
while (runCount % 10 != remainder) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(runCount + ": " + Thread.currentThread().getName());
runCount++;
lock.notifyAll();
}
}
}
And call the thread like :
Object lock = new Object();
for (int i = 0; i < 10; i++) {
new MyThread(lock, i).start();
}
You are synchronizing the context of the thread, which is different for each one. You should put into the synchronized key any common object for all diferent threads. This won't make them run in any certain secuence, just to wait each other to end.
If you want to test the synchronized keyword for any purpose, you could pass the constructor a common variable and use it in every thread:
public class MyThread extends Thread {
private static final int threadMax = 10;
private static int runCount = 0;
private Object test; //Object pointing main method
public MyThread(Object test){
this.test = test; //This won't copy values as it is an object and not a number, string...
}
public void printThread() {
synchronized (test) { //Same object for all threads
while (runCount++ < 100) {
System.out.println(runCount + ": " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void run() {
printThread();
}
public static void main(String[] args) {
Object test; //common object
for (int i = 0; i < threadMax; i++) {
new MyThread(test).start();
}
}
}
If you want also to make them start in order, you should "synchronize" the loop making wait and notify calls.
Anyway, the point about multithreading is to have several threads running at the "same" time and not in sequence, as that would be the same as a linear execution.
You have several tasks that you want to delegate to threads but have them executed sequentially.
As others have pointed out, wait & notify can help you achieve that : wait until Nth have finished then notify the next. However, if you wait/notify inside your printThread method, as all your threads are waiting simultaneously on the same lock, there is no guaranties that N+1th thread will be next. So you may have
1: thread-1
...
10: thread-1
11: thread-5
...
20: thread-5
21: thread-2
...
If that's ok for you, you're done. However, in a situation where you specifically want your threads to be ordered, what you need is a waiting queue (FIFO : First In First Out).
To achieve that, you can use the awesome ExecutorService. Be aware however that they hide the Threads from you and picking that solution should not be at the cost of understanding the basics of them beforehand.
An ExecutorService is a very convenient class that can receive tasks (in the form of a Runnable, see below) and will execute them in separate Threads.
Here, I'm using a SingleThreadExecutor which execute the submitted tasks sequentially. So all you have to do is call it's execute method with your tasks as arguments, and the ExecutorService will run them in the right order, one after the other.
Here's what you can do with a few notes :
public class ThreadRunner {
// Note : Constants are usually all uppercase in Java
private static final int MAX_THREADS = 10;
private final int threadName;
public ThreadRunner(int threadName) {
this.threadName = threadName;
}
public void printThread() {
// Note: For loops are better than while when you already know the number of iterations
for (int runCount = 0; runCount < 10; runCount++) {
System.out.println(runCount + "th run from thread " + threadName);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < MAX_THREADS; i++) {
int threadName = i + 1;
// Submit a task to the executor
executorService.execute(() -> new ThreadRunner(threadName).printThread());
}
// Nicely ask for the executor to shutdown.
// Then wait for already submitted tasks to terminate.
executorService.shutdown();
try {
executorService.awaitTermination(120, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I changed a few details, here are the reasons :
Thread creation : don't inherit from Thread
I would advise you not to inherit from Thread, but create a local instance of it, as all you need is to use a Thread ; you don't want to be a Thread :
public static void main(String[] args) {
// Using Java 1.8+ lambda
Thread lambdaThread = new Thread(() -> System.out.println("Hello from a lambda in a Thread"));
lambdaThread.start();
// Using an anonymous class for java <1.8
Thread anonClassThread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Hello from an anonymous class in a Thread");
}
});
anonClassThread.start();
}
You're creating a new Thread passing a Runnable as constructor argument, using either lambda or anonymous class, depending of your Java version.
A Runnable is simply a portion of code that will be executed (by a Thread, in this case).
Same apply to ExecutorService, it's execute methode takes a Runnable which I've created through lambdas.
Sharing static counter between threads
Your line private static int runCount = 0; is a static field, which means it is shared by all instances of the class MyThread. When you increase it in a thread, all threads will read (and write) to the same variable.
If your threads were running sequentially, the first would do it's 100 iterations, then when the second thread starts, runCount is already at 100 and you're not entering your while loop. If that wasn't intended, it may be confusing when you'll test your code.
Based on your expected output in a comment, I believe you want your threads to do 10 iterations each, not share a pool of 100 iterations and manage somehow to have each of them only perform 10.
Having the name of the thread belong to each ThreadRunner
Small detail here : previously, you were creating 10 threads. Here, the ExecutorService only creates one that he reuse for each task you submit. So Thread.currentThread().getName() would always be thread-1.
You wouldn't be able to see which task is running without this field.
If each task is started after the previous, you don't need 10 Threads, but a single Thread performing the 10 tasks sequentially.
I've been as complete as possible, but some points might be a little bit tricky, so don't hesitate to ask for clarifications!
Problem: I have collection of threads start in a loop parallelly. After exiting anyone of thread first ,all other running threads must be terminated. This is what I tried but it doesn't work. Any help is appreciated.
public class ThreadsMain {
public static void main(String[] args) {
int SIZE = 3;
Thread t[] = new Thread[SIZE];
for (int i = 0; i < SIZE; i++) {
myThreads th = new myThreads();
t[i] = new Thread(th);
t[i].start();
}
}
}
Here is one way to do it, with a synchronizer implemented with intrinsic locks, and using interruption to cancel the unfinished tasks. The data structure makes a consumer thread block until a producer has submitted a result, then it cancels the other worker threads.
This is a toy example, see the link at the end for the real-world way to do this.
First, here's a threadsafe data structure that accepts results, it allows threads to register as listeners and interrupts them once it has a result submitted to it:
class MyQueue<T> {
private java.util.List<T> results = new java.util.ArrayList<T>();
private java.util.List<Thread> listeners = new java.util.ArrayList<Thread>();
public synchronized void put(T o) {
results.add(o);
notifyAll();
for (Thread listener : listeners) {
listener.interrupt();
}
}
public synchronized T take() throws InterruptedException {
while (results.size() == 0) {
wait();
}
return results.remove(0);
}
public synchronized void addListener(Thread t) {
listeners.add(t);
}
}
(I don't like having this class know so much about the listeners but I don't want to overthink a toy example either.)
The wait method releases the lock and makes the calling thread go dormant until a notification occurs (or it can just stop waiting arbitrarily). It uses the size property of the results list to know when a result has been submitted. It's not safe to assume that because a thread stopped waiting that you can infer something about the current state, once the thread reacquires the lock it needs to check what the current state actually is. For more about how wait works see this tutorial.
Here's a task that calculates a result (sleeping between iterations just so these threads can run for a while):
class FibTask implements Runnable {
private final MyQueue<BigInteger> queue;
private final int n;
private long sleepTime;
public FibTask(int n, long sleepTime, MyQueue<BigInteger> queue) {
this.n = n;
this.sleepTime = sleepTime;
this.queue = queue;
}
#Override public void run() {
BigInteger a = BigInteger.valueOf(0);
BigInteger b = BigInteger.valueOf(1);
int i = 0;
try {
while (!Thread.currentThread().isInterrupted() && i < n) {
i = i + 1;
BigInteger temp = a;
a = b;
b = a.add(temp);
Thread.sleep(sleepTime);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (!Thread.currentThread().isInterrupted()) {
queue.put(b);
}
}
}
Notice in the code above how the Runnable needs to be aware of attempts to interrupt it. Interruption is cooperative, the task is responsible for deciding when to detect interruption and for handling the termination process.
Also if a task involves IO then in some cases interruption doesn't work and you have to close the socket, see this article for more discussion of this.
Here's the main program that runs the threads and gets the result. The MyQueue class is already doing most of the work so this doesn't have to do much:
class Completion {
public static void main(String ... args) throws Exception {
MyQueue<BigInteger> queue = new MyQueue<BigInteger>();
Thread t1 = new Thread(new FibTask(10, 1000L, queue));
Thread t2 = new Thread(new FibTask(20, 10000L, queue));
Thread t3 = new Thread(new FibTask(25, 50000L, queue));
queue.addListener(t1);
queue.addListener(t2);
queue.addListener(t3);
t1.start();
t2.start();
t3.start();
System.out.println(queue.take());
}
}
Be aware this isn't a fair race because of how the threads' starts are staggered, later threads are at a disadvantage. Submitting tasks to an Executor that initializes a threadpool up front would make sure that the time to start a thread didn't cause a delay here.
For a better way that makes use of java.util.concurrent features like Executors and Futures, see the example given in the API documentation for ExecutorCompletionService.
A simple approach, use a synchronized class to handle the loop condition:
class ThreadHandler
{
static Object lock = new Object();
static boolean finished = false;
static void finishThreads()
{
synchronized(lock)
{
finished = true;
}
}
static boolean isFinished()
{
boolean result;
synchronized(lock)
{
result = finished;
}
return result;
}
}
And in your runnable
class myThreads implements Runnable
{
#Override
public void run()
{
while(!ThreadHandler.isFinished())
{
}
}
}
How can I make Callable thread as daemon thread?
Here is what I am trying. I am trying to execute a set of threads of which one of them does not complete and goes into infinite loop. What it does is the main thread of the program does not terminate even though all the code statements are executed. The main thread goes into suspended mode after that.
Here is the code snippet for the same.
public class MyThread implements Callable<String> {
private int value;
public MyThread(int value) {
this.value = value;
}
#Override
public String call() throws Exception {
//Thread.currentThread().setDaemon(true);
System.out.println("Executing - " + value);
if (value == 4) {
for (; ; );
}
return value + "";
}
}
Main Program
public class ExecutorMain {
public static String testing() {
ExecutorService executor = null;
List<Future<String>> result = null;
String parsedValue = null;
try {
executor = Executors.newSingleThreadExecutor();
List<MyThread> threads = new ArrayList<MyThread>();
for (int i = 1; i < 10; i++) {
MyThread obj = new MyThread(i);
threads.add(obj);
}
result = executor.invokeAll(threads, Long.valueOf("4000"), TimeUnit.MILLISECONDS);
//result = executor.invokeAll(threads);
for (Future<String> f : result) {
try {
parsedValue = f.get();
System.out.println("Return Value - " + parsedValue);
} catch (CancellationException e) {
System.out.println("Cancelled");
parsedValue = "";
f.cancel(true);
}
}
executor.shutdownNow();
} catch (Exception e) {
System.out.println("Exception while running threads");
e.printStackTrace();
} finally {
List executedThreads = executor.shutdownNow();
System.out.println(executedThreads);
for (Object o : executedThreads) {
System.out.println(o.getClass());
}
}
System.out.println("Exiting....");
//System.exit(1);
return "";
}
public static void main(String[] args) {
testing();
}
}
What I got to understand from my earlier question about Dangling threads in Java is that I have to make my threads as daemon threads.
How can I make Callable thread as daemon thread?
You need to use a new ThreadFactory that creates daemon threads. See this answer here: Executor and Daemon in Java
By default the executors create non-daemon threads whenever they build their pools. But you can inject your own ThreadFactory which creates the threads for the pool.
For example:
executor = ExecutorService.newSingleThreadExecutor(new MyThreadFactory());
The ThreadFactory implements the newThread method:
Thread newThread(Runnable r)
Copied from the answer I linked to above, you could implement it like:
class MyThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
}
You mentioned in your question:
//Thread.currentThread().setDaemon(true);
Yeah, this won't work because you cannot set the daemon flag once the thread has been started.
It is not about making Callable to daemon. You actually want to make the execute threads become daemon. You can create the thread in this way to make it becomes daemon:
executor = Executors.newSingleThreadExecutor(new ThreadFactory(){
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
Just setting the Threads created by the ExecutorService to daemon won't help (though you do need to do this). You can set your ExecutorService Threads to daemon like so:
executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
});
The real problem you are having is with this code block:
for (Future<String> f : result) {
try {
parsedValue = f.get();
System.out.println("Return Value - " + parsedValue);
} catch (CancellationException e) {
System.out.println("Cancelled");
parsedValue = "";
f.cancel(true);
}
}
executor.shutdownNow();
More specifically, this code will hang forever here:
parsedValue = f.get();
The reason for this is simple, the Future#get method "Waits if necessary for the computation to complete, and then retrieves its result.", but the computation will never complete because it is in an infinite loop. Not even an interrupt from ThreadPoolExecutor#shutdownNow or Future#cancel(true) will help you because your Callable code is not perofrming a blocking operation or otherwise checking for an interrupt.
From here, you have two options:
Use the form of Future#get that takes a long timeout argument.
Use Future#isDone to determine if the Future#get method has a value to return prior to actually calling Future#get.
Thanks Tim for the detailed explanation. However, your proposed solution did not solve the issue. The problem was that because the thread has gone to infinite loop, it does not check for any thread interruption and hence does not terminate.
For my scenario, infinite loop is not a good example, but what we were trying to accomplish is that we were executing a regular expression which was taking too long to execute and the check for interruption was after matcher.find() call. Because find() does not return in stipulated time and also the find() method does not check for thread interruptions, we were facing the dangling thread issue. Finally, implemented InterruptableCharSequence from this url and got it working.
I have few asynchronous tasks running and I need to wait until at least one of them is finished (in the future probably I'll need to wait util M out of N tasks are finished).
Currently they are presented as Future, so I need something like
/**
* Blocks current thread until one of specified futures is done and returns it.
*/
public static <T> Future<T> waitForAny(Collection<Future<T>> futures)
throws AllFuturesFailedException
Is there anything like this? Or anything similar, not necessary for Future. Currently I loop through collection of futures, check if one is finished, then sleep for some time and check again. This looks like not the best solution, because if I sleep for long period then unwanted delay is added, if I sleep for short period then it can affect performance.
I could try using
new CountDownLatch(1)
and decrease countdown when task is complete and do
countdown.await()
, but I found it possible only if I control Future creation. It is possible, but requires system redesign, because currently logic of tasks creation (sending Callable to ExecutorService) is separated from decision to wait for which Future. I could also override
<T> RunnableFuture<T> AbstractExecutorService.newTaskFor(Callable<T> callable)
and create custom implementation of RunnableFuture with ability to attach listener to be notified when task is finished, then attach such listener to needed tasks and use CountDownLatch, but that means I have to override newTaskFor for every ExecutorService I use - and potentially there will be implementation which do not extend AbstractExecutorService. I could also try wrapping given ExecutorService for same purpose, but then I have to decorate all methods producing Futures.
All these solutions may work but seem very unnatural. It looks like I'm missing something simple, like
WaitHandle.WaitAny(WaitHandle[] waitHandles)
in c#. Are there any well known solutions for such kind of problem?
UPDATE:
Originally I did not have access to Future creation at all, so there were no elegant solution. After redesigning system I got access to Future creation and was able to add countDownLatch.countdown() to execution process, then I can countDownLatch.await() and everything works fine.
Thanks for other answers, I did not know about ExecutorCompletionService and it indeed can be helpful in similar tasks, but in this particular case it could not be used because some Futures are created without any executor - actual task is sent to another server via network, completes remotely and completion notification is received.
simple, check out ExecutorCompletionService.
ExecutorService.invokeAny
Why not just create a results queue and wait on the queue? Or more simply, use a CompletionService since that's what it is: an ExecutorService + result queue.
This is actually pretty easy with wait() and notifyAll().
First, define a lock object. (You can use any class for this, but I like to be explicit):
package com.javadude.sample;
public class Lock {}
Next, define your worker thread. He must notify that lock object when he's finished with his processing. Note that the notify must be in a synchronized block locking on the lock object.
package com.javadude.sample;
public class Worker extends Thread {
private Lock lock_;
private long timeToSleep_;
private String name_;
public Worker(Lock lock, String name, long timeToSleep) {
lock_ = lock;
timeToSleep_ = timeToSleep;
name_ = name;
}
#Override
public void run() {
// do real work -- using a sleep here to simulate work
try {
sleep(timeToSleep_);
} catch (InterruptedException e) {
interrupt();
}
System.out.println(name_ + " is done... notifying");
// notify whoever is waiting, in this case, the client
synchronized (lock_) {
lock_.notify();
}
}
}
Finally, you can write your client:
package com.javadude.sample;
public class Client {
public static void main(String[] args) {
Lock lock = new Lock();
Worker worker1 = new Worker(lock, "worker1", 15000);
Worker worker2 = new Worker(lock, "worker2", 10000);
Worker worker3 = new Worker(lock, "worker3", 5000);
Worker worker4 = new Worker(lock, "worker4", 20000);
boolean started = false;
int numNotifies = 0;
while (true) {
synchronized (lock) {
try {
if (!started) {
// need to do the start here so we grab the lock, just
// in case one of the threads is fast -- if we had done the
// starts outside the synchronized block, a fast thread could
// get to its notification *before* the client is waiting for it
worker1.start();
worker2.start();
worker3.start();
worker4.start();
started = true;
}
lock.wait();
} catch (InterruptedException e) {
break;
}
numNotifies++;
if (numNotifies == 4) {
break;
}
System.out.println("Notified!");
}
}
System.out.println("Everyone has notified me... I'm done");
}
}
As far as I know, Java has no analogous structure to the WaitHandle.WaitAny method.
It seems to me that this could be achieved through a "WaitableFuture" decorator:
public WaitableFuture<T>
extends Future<T>
{
private CountDownLatch countDownLatch;
WaitableFuture(CountDownLatch countDownLatch)
{
super();
this.countDownLatch = countDownLatch;
}
void doTask()
{
super.doTask();
this.countDownLatch.countDown();
}
}
Though this would only work if it can be inserted before the execution code, since otherwise the execution code would not have the new doTask() method. But I really see no way of doing this without polling if you cannot somehow gain control of the Future object before execution.
Or if the future always runs in its own thread, and you can somehow get that thread. Then you could spawn a new thread to join each other thread, then handle the waiting mechanism after the join returns... This would be really ugly and would induce a lot of overhead though. And if some Future objects don't finish, you could have a lot of blocked threads depending on dead threads. If you're not careful, this could leak memory and system resources.
/**
* Extremely ugly way of implementing WaitHandle.WaitAny for Thread.Join().
*/
public static joinAny(Collection<Thread> threads, int numberToWaitFor)
{
CountDownLatch countDownLatch = new CountDownLatch(numberToWaitFor);
foreach(Thread thread in threads)
{
(new Thread(new JoinThreadHelper(thread, countDownLatch))).start();
}
countDownLatch.await();
}
class JoinThreadHelper
implements Runnable
{
Thread thread;
CountDownLatch countDownLatch;
JoinThreadHelper(Thread thread, CountDownLatch countDownLatch)
{
this.thread = thread;
this.countDownLatch = countDownLatch;
}
void run()
{
this.thread.join();
this.countDownLatch.countDown();
}
}
If you can use CompletableFutures instead then there is CompletableFuture.anyOf that does what you want, just call join on the result:
CompletableFuture.anyOf(futures).join()
You can use CompletableFutures with executors by calling the CompletableFuture.supplyAsync or runAsync methods.
Since you don't care which one finishes, why not just have a single WaitHandle for all threads and wait on that? Whichever one finishes first can set the handle.
See this option:
public class WaitForAnyRedux {
private static final int POOL_SIZE = 10;
public static <T> T waitForAny(Collection<T> collection) throws InterruptedException, ExecutionException {
List<Callable<T>> callables = new ArrayList<Callable<T>>();
for (final T t : collection) {
Callable<T> callable = Executors.callable(new Thread() {
#Override
public void run() {
synchronized (t) {
try {
t.wait();
} catch (InterruptedException e) {
}
}
}
}, t);
callables.add(callable);
}
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(POOL_SIZE);
ExecutorService executorService = new ThreadPoolExecutor(POOL_SIZE, POOL_SIZE, 0, TimeUnit.SECONDS, queue);
return executorService.invokeAny(callables);
}
static public void main(String[] args) throws InterruptedException, ExecutionException {
final List<Integer> integers = new ArrayList<Integer>();
for (int i = 0; i < POOL_SIZE; i++) {
integers.add(i);
}
(new Thread() {
public void run() {
Integer notified = null;
try {
notified = waitForAny(integers);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("notified=" + notified);
}
}).start();
synchronized (integers) {
integers.wait(3000);
}
Integer randomInt = integers.get((new Random()).nextInt(POOL_SIZE));
System.out.println("Waking up " + randomInt);
synchronized (randomInt) {
randomInt.notify();
}
}
}