Locking only on a single entry point - java

I am utilizing an ExcutorService to submit tasks to run in parallel. The order of the tasks does not matter. However, the service may change, specifically when the requested size of the pool needs to change.
public class Service {
private volatile ExecutorService service = Executors.newFixedThreadPool(4);
private final ReentrantLock serviceLock = new ReentrantLock();
public Future<Object> postRequest(final Callable<Object> request) {
try {
serviceLock.lock(); // ?
return service.submit(request);
} finally {
serviceLock.unlock(); // ?
}
}
public void setSize(final int size) {
try {
if (size <= 0) {
throw new IllegalArgumentException("service pool size must positive");
}
serviceLock.lock();
service = Executors.newFixedThreadPool(size);
} finally {
serviceLock.unlock();
}
}
}
Obviously, I don't think I need the locking and unlocking in the postRequest method when it is the only method being called.
I only need to lock on postRequest during access to setSize. Otherwise, the extra time required to lock and unlock is just pointless. I believe this is necessary, seeing as the size will rarely change (maybe once or twice) compared to hundreds of requests being submitted.
Is there a way to avoid the locking on postRequest when it is not needed (when setSize is not being accessed)?

Since the Executor is in fact a ThreadPoolExecutor you can apply a cast and use its setMaximumPoolSize method.
You may add a type check in the setSize method in case of a future update of the JVM spec.
if (e instanceof ThreadPoolExecutor) {
((ThreadPoolExecutor) e).setMaximumPoolSize(size);
}
See https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html#setMaximumPoolSize(int)

#Obicere, you are right, you dont need to lock on postRequest which will have performance overhead.
Use something like this inside postRequest
public Future<Object> postRequest(final Callable<Object> request) {
try {
while(serviceLock.isLocked()) { // i.e acquired by setSize method
Thread.currentThread().sleep(/*some very small time */);
}
return service.submit(request);
} finally {
}
}
Also, please consider using ThreadPoolExecutor instead of FixedPoolThread because in your case, it was never a fixed pool thread :)

You can create a thread pool executor explicitly and then use setMaximumPoolSize():
private final ThreadPoolExecutor service = new ThreadPoolExecutor(4,4,0, TimeUnit.MINUTE, new LinkedBlockingQueue());
public void setSize(final int size) {
service.setMaximumPoolSize(size);
}

Related

Java how to get a map value in future?

Here's pseudo code:
//-- Thread A
sender.send(requestId, request);
// Wait receiver to receive response for that requestId
return requestIdToResponseMap.get(requestId);
//--- Thread B
response = receiver.receive();
requestIdToResponseMap.put(response.requestId, response);
Note:
The call to downstream service is:
time consuming
asynchronized (i.e. response for request can only be mapped by request-id)
Let's say downstream service is a websocket client. The server sends messages and waits for responses.
About the requestIdToResponseMap, I tried 3 solutions:
Use a requestIdToLockMap to hold the locks, and use requestIdToResponseMap to hold the response values, but it seems complicated.
Use Map< String, Optional< Response>>, but Optional is immutable, I can not change its value. This doesn't work.
Use Map< String, Pair< Lock, Response>>, the receiver notifies the corresponding lock, then sender thread gets notified and retrieves the value.
So, for this kind of problem, what's the usual solution?
You didn't go into detail on your use case, so I'll answer the question generally:
Java has an entire framework for multi-threaded consumer-producer cases. If you find yourself thinking about locks and thread primitives, you're probably reinventing the wheel. Focus on the important stuff :-)
Here's a snippet to get you started:
// create your thread pool, threads here will consume your "requests"
ExecutorService threadPool = Executors.newFixedThreadPool(1);
// submit a request to the pool. This gets enqueued on a queue, until it is picked up by a thread. Returns a future- a reference to the uncompleted work
Future<Response> future = threadPool.submit(new RequestTask<Response>(request, requestId));
// wait for the work to complete
Response response = future.get();
your RequestTask implements Callable:
private static class RequestTask implements Callable<Response> {
#Override
public Response call() throws Exception {
...
}
}
Just to be clear, your producer thread is the "main" thread (A in your example) and the consumer is in the thread pool (thread B). You can increase your thread pool size (to a certain extent) to increase your request throughput.
There's tons of references about Java's ExecutorService and producer-consumer pattern. Remember that you have a queue in between producer and consumer threads, since you may produce requests faster than you can consume. It's unbounded by default, very important to remember that!
Let us know if you have any more questions.
Create map which will store reponsefuture which will be blocking if result is not available thread will wait .You can modify with other functionality like wait for how much time.
private static ConcurrentHashMap<String, ExecutorSeriveInstanceFuture> instanceMap = new ConcurrentHashMap<String, ExecutorSeriveInstanceFuture>();
customize Future so you can modify according to your use case.
private static class ExecutorSeriveInstanceFuture {
private DBExecutorSerive dbExecutorSerive;
private Throwable throwable;
private Object lock = new Object();
public DBExecutorSerive get() {
if (dbExecutorSerive == null) {
return dbExecutorSerive;
}
boolean restoreInterrupt = false;
synchronized (lock) {
while (dbExecutorSerive == null && throwable == null) {
try {
lock.wait();
} catch (InterruptedException e) {
restoreInterrupt = true;
}
}
}
if (restoreInterrupt) {
Thread.currentThread().interrupt();
}
if (dbExecutorSerive != null) {
return dbExecutorSerive;
}
throw new IllegalStateException(throwable);
}
public void set(DBExecutorSerive dbExecutorSerive) {
synchronized (lock) {
this.dbExecutorSerive = dbExecutorSerive;
lock.notifyAll();
}
}
public void setFailure(Throwable throwable) {
synchronized (lock) {
this.throwable = throwable;
lock.notifyAll();
}
}
}

Beginner Java Multithreading issue

I have a problem with a Java multithreaded file crawler that I am making. My issue is that I have a workQueue that is a linkedBlockingQueue that contains the names of files that I would like to crawl over with my threads, each thread will take() from the workQueue and while scanning through the file it may put() another file name into the workQueue (It is a dependency checker program). So I am never really certain when the work is all finished and all threads will eventually enter a waiting state when they try to take() from the (eventually) empty workQueue.
So I guess my question is, is there an efficient way to terminate all of threads once all of the work is finished (when all of threads have entered a waiting state)? Currently I just use sleep() on the main thread and then interrupt() all of the worker threads.
Sorry if the question sounds confused.
I've had this problem before, and the only way I found was to send a special marker object to the BlockingQueue. When the Queue .take() the object, if this is the marker, then the Thread ends itself.
I've tried other solutions, like to wake up the thread and detect the Exception, with no success.
There's a pattern called the Poison Pill that's good for this. Basically, when the producers are done, insert a special value into the queue that tells a consumer to stop. You can either insert one pill for each consumer, or, once a consumer gets a poison pill, return it to the queue for the next consumer. Since it sounds like you're just enqueuing strings, something like
public static final String POISON_PILL = "DONE";
Or in Java 8, use Optional to wrap your values, then have not present be the pill.
BlockingQueue<Optional<...>> queue;
Another option is using an ExecutorService (which is actually backed by a BlockingQueue) and submitting each file as its own task, then using executorService.shutdown() when you're done. The problem with this is that it couples your code more tightly than needed, and it makes it harder to reuse resources like database and HTTP connections.
I'd avoid interrupting your workers to signal them because that can cause blocking IO operations to fail.
You might use the approch below. Add observer pattern if you need to.
Or simply - instead of signalling with a death packet, collect a list of waiting Threads and then interrupt() them.
public class AccessCountingLinkedPrioQueue<T> {
private final LinkedBlockingQueue<T> mWrappingQueue = new LinkedBlockingQueue<>();
private final Object mSyncLockObj = new Object();
private final int mMaxBlockingThreads;
private final T mDeathSignallingObject;
private volatile int mNumberOfThreadsInAccessLoop = 0;
public AccessCountingLinkedPrioQueue(final int pMaxBlockingThreads, final T pDeathSignallingObject) {
mMaxBlockingThreads = pMaxBlockingThreads;
mDeathSignallingObject = pDeathSignallingObject;
}
public T take() throws InterruptedException {
final T retVal;
synchronized (mSyncLockObj) {
++mNumberOfThreadsInAccessLoop;
}
synchronized (mWrappingQueue) {
if (mNumberOfThreadsInAccessLoop >= mMaxBlockingThreads && mWrappingQueue.isEmpty()) signalDeath();
retVal = mWrappingQueue.take();
}
synchronized (mSyncLockObj) {
--mNumberOfThreadsInAccessLoop;
}
return retVal;
}
private void signalDeath() {
for (int i = 0; i < mMaxBlockingThreads; i++) {
mWrappingQueue.add(mDeathSignallingObject);
}
}
public int getNumberOfThreadsInAccessLoop() {
return mNumberOfThreadsInAccessLoop;
}
}
class WorkPacket {
// ... your content here
}
class MultiThreadingBoss {
static public final WorkPacket DEATH_FROM_ABOVE = new WorkPacket();
public MultiThreadingBoss() {
final int THREADS = 7;
final AccessCountingLinkedPrioQueue<WorkPacket> prioQ = new AccessCountingLinkedPrioQueue<>(THREADS, DEATH_FROM_ABOVE);
for (int i = 0; i < THREADS; i++) {
final ThreadedWorker w = new ThreadedWorker(prioQ);
new Thread(w).start();
}
}
}
class ThreadedWorker implements Runnable {
private final AccessCountingLinkedPrioQueue<WorkPacket> mPrioQ;
public ThreadedWorker(final AccessCountingLinkedPrioQueue<WorkPacket> pPrioQ) {
mPrioQ = pPrioQ;
}
#Override public void run() {
while (true) {
try {
final WorkPacket p = mPrioQ.take();
if (p == MultiThreadingBoss.DEATH_FROM_ABOVE) break; // or return
// ... do your normal work here
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
}
}

Is there an out-of-the-box thread pool with multiple queues (that ensure serial processing of each queue)?

Among all my tasks, I have some that must be processed serially (they can never run concurrently and they must be processed in order).
I achieved that creating a separated thread pool with a single thread for each group of tasks that must be executed serially. It works but I don't have the resources for that. I don't control the number of groups, so I might end up with a ridiculous number of threads running simultaneously.
Is there any way I can accomplish that with a single thread pool? Is there a thread pool with multiple blocking queues where I could ensure serial execution for each queue?
EDIT:
Just emphasizing what I've said in my second paragraph: I've solved this with a single threaded thread pool for each group of tasks that must be executed serially. I can't go on with this solution, though. There are way too many groups and I can't have all these threads.
I've found this related question, but since it is not very recent, I still created mine. All I'm doing is trying to avoid reinventing the wheel, but it seems I don't have a choice.
Does Java have an indexable multi-queue thread pool?
If you maintain a queue for each group, you can pull items off each queue and feed them into a thread pool. The code below won't prioritize any one group, it just pulls them in a round-robin fashion. If you need to add prioritization you should easily be able to. The following code will round-robin 4 groups using two threads (plus the thread managing the queue). You can use another queue mechanism. I typically use LinkedBlockingQueue for situations where I want to wait for items to be placed on the queue by another thread, which probably is not what you want - so I'm polling instead of calling take(). Take is the call that waits.
private Future group1Future = null;
private Future group2Future = null;
private Future group3Future = null;
private Future group4Future = null;
private LinkedBlockingQueue<Callable> group1Queue
= new LinkedBlockingQueue<>();
private LinkedBlockingQueue<Callable> group2Queue
= new LinkedBlockingQueue<>();
private LinkedBlockingQueue<Callable> group3Queue
= new LinkedBlockingQueue<>();
private LinkedBlockingQueue<Callable> group4Queue
= new LinkedBlockingQueue<>();
private ExecutorService executor = Executors.newFixedThreadPool(2);
public void startProcessing() {
while (true) {
if (group1Future != null && group1Future.isDone()) {
if (group1Queue.peek() != null) {
group1Future = executor.submit(group1Queue.poll());
}
}
if (group2Future != null && group1Future.isDone()) {
if (group2Queue.peek() != null) {
group2Future = executor.submit(group2Queue.poll());
}
}
if (group3Future != null && group3Future.isDone()) {
if (group3Queue.peek() != null) {
group3Future = executor.submit(group3Queue.poll());
}
}
if (group4Future != null && group4Future.isDone()) {
if (group4Queue.peek() != null) {
group4Future = executor.submit(group4Queue.poll());
}
}
}
}
If a task for that group is not complete, it will skip to the next group. No more than two groups will be processed at a time and no single group will ever run more than one task. The queues will enforce ordered execution.
Akka, as suggested by #SotiriosDelimanolis and #AlexeiKaigorodov seems promising, as well as #Dodd10x second answer, which certainly solves the problem. The only downside is that I'd have to code my own polling strategy to make sure my tasks are eventually added to the executor (like the infinite loop in his example).
On the other hand, the Striped Executor Service suggested by #OldCurmudgeon exactly matches my problem and works out of the box simply as a custom ExecutorService.
This magical thread pool would ensure that all Runnables with the same stripeClass would be executed in the order they were submitted, but StripedRunners with different stripedClasses could still execute independently. He wanted to use a relatively small thread pool to service a large number of Java NIO clients, but in such a way that the runnables would still be executed in-order.
There is even a comment about using a single threaded thread pool for each group (stripe), as it was suggested here:
Several suggestions were made, such as having a SingleThreadExecutor for each stripeClass. However, that would not satisfy the requirement that we could share the threads between connections.
I see this as the best solution for its simplicity and ease of use.
I recently answered a question about a "serial task queue" with a basic implementation as demonstration here. I imagine you have been using a similar solution. It is relatively easy to adapt the implementation to use a map of task lists and still share one (fixed size) executor.
The Striped Executor Service you mention is the better solution, but I show the adapted implementation here to demonstrate decoupling the task queue(s) from the executor. The implementation uses a callback and therefor has no need to do polling or signalling. Since a "critical (stop the world) section" is used, the map with task queues can clean itself: no tasks queued means empty map. Downside of the "critical section" is that throughput is limited: only so many tasks can be added and removed per second.
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
// Copied and updated from https://stackoverflow.com/a/32916943/3080094
public class SerialTaskQueues {
public static void main(String[] args) {
// test the serial task execution using different groups
ExecutorService executor = Executors.newFixedThreadPool(2);
SerialTaskQueues tq = new SerialTaskQueues(executor);
try {
// test running the tasks one by one
tq.add(new SleepSome("1", 30L));
Thread.sleep(5L);
tq.add(new SleepSome("2", 20L));
tq.add(new SleepSome("1", 10L));
Thread.sleep(100L);
// all queues should be empty
System.out.println("Queue size 1: " + tq.size("1")); // should be empty
System.out.println("Queue size 2: " + tq.size("2")); // should be empty
tq.add(new SleepSome("1", 10L));
tq.add(new SleepSome("2", 20L));
// with executor pool size set to 2, task 3 will have to wait for task 1 to complete
tq.add(new SleepSome("3", 30L));
tq.add(new SleepSome("1", 20L));
tq.add(new SleepSome("2", 10L));
Thread.sleep(100L);
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdownNow();
}
}
// all lookups and modifications to the list must be synchronized on the list.
private final Map<String, GroupTasks> taskGroups = new HashMap<>();
// make lock fair so that adding and removing tasks is balanced.
private final ReentrantLock lock = new ReentrantLock(true);
private final ExecutorService executor;
public SerialTaskQueues(ExecutorService executor) {
this.executor = executor;
}
public boolean add(String groupId, Runnable task) {
lock.lock();
try {
GroupTasks gt = taskGroups.get(groupId);
if (gt == null) {
gt = new GroupTasks(groupId);
taskGroups.put(groupId, gt);
}
gt.tasks.add(task);
} finally {
lock.unlock();
}
runNextTask(groupId);
return true;
}
/* Utility method for testing. */
public void add(SleepSome sleepTask) {
add(sleepTask.groupId, sleepTask);
}
private void runNextTask(String groupId) {
// critical section that ensures one task is executed.
lock.lock();
try {
GroupTasks gt = taskGroups.get(groupId);
if (gt.tasks.isEmpty()) {
// only cleanup when last task has executed, prevent memory leak
if (!gt.taskRunning.get()) {
taskGroups.remove(groupId);
}
} else if (!executor.isShutdown() && gt.taskRunning.compareAndSet(false, true)) {
executor.execute(wrapTask(groupId, gt.taskRunning, gt.tasks.remove(0)));
}
} finally {
lock.unlock();
}
}
private CallbackTask wrapTask(final String groupId, final AtomicBoolean taskRunning, Runnable task) {
return new CallbackTask(task, new Runnable() {
#Override
public void run() {
if (!taskRunning.compareAndSet(true, false)) {
System.out.println("ERROR: programming error, the callback should always run in execute state.");
}
runNextTask(groupId);
}
});
}
/** Amount of (active) task groups. */
public int size() {
int size = 0;
lock.lock();
try {
size = taskGroups.size();
} finally {
lock.unlock();
}
return size;
}
public int size(String groupId) {
int size = 0;
lock.lock();
try {
GroupTasks gt = taskGroups.get(groupId);
size = (gt == null ? 0 : gt.tasks.size());
} finally {
lock.unlock();
}
return size;
}
public Runnable get(String groupId, int index) {
Runnable r = null;
lock.lock();
try {
GroupTasks gt = taskGroups.get(groupId);
r = (gt == null ? null : gt.tasks.get(index));
} finally {
lock.unlock();
}
return r;
}
public Runnable remove(String groupId, int index) {
Runnable r = null;
lock.lock();
try {
GroupTasks gt = taskGroups.get(groupId);
r = gt.tasks.remove(index);
// similar to runNextTask - cleanup if there are no tasks (running) for the group
if (gt.tasks.isEmpty() && !gt.taskRunning.get()) {
taskGroups.remove(groupId);
}
} finally {
lock.unlock();
}
return r;
}
/* Helper class for the task-group map. */
class GroupTasks {
final List<Runnable> tasks = new LinkedList<Runnable>();
// atomic boolean used to ensure only 1 task is executed at any given time
final AtomicBoolean taskRunning = new AtomicBoolean(false);
final String groupId;
GroupTasks(String groupId) {
this.groupId = groupId;
}
}
// general callback-task, see https://stackoverflow.com/a/826283/3080094
static class CallbackTask implements Runnable {
private final Runnable task, callback;
public CallbackTask(Runnable task, Runnable callback) {
this.task = task;
this.callback = callback;
}
#Override
public void run() {
try {
task.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
callback.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
// task that just sleeps for a while
static class SleepSome implements Runnable {
static long startTime = System.currentTimeMillis();
private final String groupId;
private final long sleepTimeMs;
public SleepSome(String groupId, long sleepTimeMs) {
this.groupId = groupId;
this.sleepTimeMs = sleepTimeMs;
}
#Override public void run() {
try {
System.out.println(tdelta(groupId) + "Sleeping for " + sleepTimeMs + " ms.");
Thread.sleep(sleepTimeMs);
System.out.println(tdelta(groupId) + "Slept for " + sleepTimeMs + " ms.");
} catch (Exception e) {
e.printStackTrace();
}
}
private String tdelta(String groupId) { return String.format("% 4d [%s] ", (System.currentTimeMillis() - startTime), groupId); }
}
}
A single thread executor will do
ExecutorService executorService = Executors.newSingleThreadExecutor();
Which internally uses a ThreadPoolExecutor with a LinkedBlockingQueue
new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()))
So you can use this for your sequential stuff and probably use a multi-threaded executor service for concurrent tasks
Look into Java's built-in thread executor service.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html
There is a single thread executor that will process each task synchronously.
In response to the comments section:
Please read the API before you say this won't work.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor()
Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
Note: is states they are guaranteed to execute sequentially.
EDIT:
Now that I understand your question better, I have an idea you could try. If you maintain a queue for each group, you can pull items off each queue and feed them into a thread pool. The code below won't prioritize any one group, it just pulls them in a round robbing fashion. If you need to add prioritization you should easily be able to. The following code will round robbing 4 groups using two threads (plus the thread managing the queue). You can use another queue mechanism. I typically use LinkedBlockingQueue for situations where I want to wait for items to be placed on the queue by another thread, which probably is not what you want - which is why I'm polling instead of calling take(). Take is the call that waits.
private Future group1Future = null;
private Future group2Future = null;
private Future group3Future = null;
private Future group4Future = null;
private LinkedBlockingQueue<Callable> group1Queue
= new LinkedBlockingQueue<>();
private LinkedBlockingQueue<Callable> group2Queue
= new LinkedBlockingQueue<>();
private LinkedBlockingQueue<Callable> group3Queue
= new LinkedBlockingQueue<>();
private LinkedBlockingQueue<Callable> group4Queue
= new LinkedBlockingQueue<>();
private ExecutorService executor = Executors.newFixedThreadPool(2);
public void startProcessing() {
while (true) {
if (group1Future != null && group1Future.isDone()) {
if (group1Queue.peek() != null) {
group1Future = executor.submit(group1Queue.poll());
}
}
if (group2Future != null && group1Future.isDone()) {
if (group2Queue.peek() != null) {
group2Future = executor.submit(group2Queue.poll());
}
}
if (group3Future != null && group3Future.isDone()) {
if (group3Queue.peek() != null) {
group3Future = executor.submit(group3Queue.poll());
}
}
if (group4Future != null && group4Future.isDone()) {
if (group4Queue.peek() != null) {
group4Future = executor.submit(group4Queue.poll());
}
}
}
}
If a task for that group is not complete, it will skip to the next group. No more than two groups will be processed at a time and no single group will ever run more than one task. The queues will enforce ordered execution.
What you need is not a special executor, but means to express dependencies between tasks. Instead of a group of tasks which must be executed serially, think of a task which, at the end of execution, sends a signal to the next task, thus starting its execution. So your task can be coded as an actor which waits for allowing signal to start execution. Consider Akka or any other actor library (e.g. mine df4j).
There is no standard implementation of thread pool with these requirements.
Striped Executor Service mentioned in the accepted answer is a good substitute.
The disadvantages I see are: multiple queues (no way to limit queue capacity, or maintain a submission order), thread per stripe (if you have a lot of stripes, your thread pool will grow).
I decided to create similar implementation with single queue:
GitHub - TaggedThreadPoolExecutor.java
It implements standard ExecutorService interface, maintain single queue, takes a maximum number of threads as a parameter, support different rejection policies (similar to standard ThreadPoolExecutor), unlike ThreadPoolExecutor it starts new thread not when queue is full, but when new task is submitted.
You could maintain a bunch of queues (List or a Map of queues). Each queue hold a task for that specific class, and have a background running thread which will dequeue tasks from each queue serially and submit them on a separate threadpool executor which could be a bigger in size in terms of number of threads!

Waiting for an unknown number of asynchronous tasks

I have a queue of tasks, and a thread that peek the queue once in a few seconds and if there is a task it performs it.
I have another code section (in another thread of course), that creates tasks in a loop (I can't know the number of tasks in advance from outside the loop) and insert them to the queue. The tasks contains some 'result' object, and the external thread (which created those tasks) need to wait for all the tasks to finish and finally get the result from each one of them.
The problem is that I can't pass java Semaphore\CountDownLatch etc to the result object since I don't know the number of monitors in advance.
I also can't use an Executor that uses invokeAll or wait for the Future object since the tasks are unsynchrnized (the external thread just pust the task to a queue and another thread will execute the task when he have time for this).
The only solution I've had in mind is to create some 'Inverted Semaphore' class that holds a set of results and a monitors counter. The getResult function will check if the counter == 0 and if the answer is yes will notify some lock object, and the getResult function will wait for this lock:
public class InvertedSemaphore<T> {
Set<T> resultSet;
int usages;
final Object c;
public InvertedSemaphore() {
resultSet = Collections.synchronizedSet(new HashSet<T>());
usages = 0;
c = new Object();
}
public void addResult(T result) {
resultSet.add(result);
}
public void addResults(Set<T> result) {
resultSet.addAll(result);
}
public void acquire() {
usages++;
}
public void release() {
synchronized (c) {
if (--usages == 0) {
c.notify();
}
}
}
public Set<T> getResults() {
synchronized (c) {
try {
while (usages > 0) {
c.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return resultSet;
}
}
Each addTask method will invoke semaphore.acquire, and each of the (unsynchronized) tasks will invoke semaphore.release in the end of the task.
It sounds pretty complicated and I'm pretty sure there is a better solution for this in java concurrent library or something.
Any idea will be appriciated:)
If the tasks don't need to be processed in order, use an ExecutorCompletionService
More generally, it is not necessary to use invokeAll on an ExecutorService in order to get a Future for the result. ExecutorService#submit could be used for this purpose, or optionally, the task being created could implement Future itself, thus allowing the creator of the task to ask for the result at a later point in time.
Some code:
class MyTask {
AtomicReference<?> result = new AtomicReference<?>();
void run() {
//do stuff here
result.set(/* the result of the calculation */);
}
boolean resultReady() {
return result.get()!=null;
}
? get() {
return result.get();
}
}
... elsewhere in code
void createTasks() {
Collection<MyTask> c = new ...;
while(indeterminable condition) {
MyTask task = new MyTask();
c.add(task);
mysteryQueue.add(task);
}
while(haven't received all results) {
MyTask task = c.get(...); //or iterate or whatever
? result = task.get();
if (result!=null) {
//do stuff, probably remove the task from the collection c would be smart
}
}
}
One idea would be to use a separate queue for the results.
So you will have one blocking queue that thread A places tasks for thread B thereby having a producer-consumer approach, and when each task is completed, the result could be placed in the second result queue inverting the consumer-producer roles since now thread A that originally created the tasks will consume the result from the second queue.
You can do the following:
each producer will hold its own queue. The producer will pass a means to report to this queue to the Task itself. When the task finishes running, it will queue its result to this queue. It is beast described by some code:
class Result{}
interface IResultCallback{
void resultReady(Result r); // this is an abstraction of the queue
}
class Producer implements IResultCallback{
// the producer needs to pass itself to the constructor of the task,
// the task will only see its "resultReady" facade and will be able to report to it.
// the producer can aggragte the results at it will and execute its own computation as
// as soon it is ready
Queue<Result> results; // = init queue
#Override
public void resultReady(Result r) {
results.add(r);
if(results.size() == 9){
operate();
}
results.clear();
}
public void operate(){
// bla bla
}
}
public class Task {
IResultCallback callback;
public Task(IResultCallback callback){
this.callback = callback;
}
public void execute(){
// bla bla
Result r = null; // init result;
callback.resultReady(r);
}
}

Wait until any of Future<T> is done

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();
}
}
}

Categories

Resources