What is java's equivalent of ManualResetEvent? [duplicate] - java

This question already has answers here:
Java Equivalent of .NET's ManualResetEvent and WaitHandle
(4 answers)
Closed 4 years ago.
What is java's equivalent of ManualResetEvent?

class ManualResetEvent {
private final Object monitor = new Object();
private volatile boolean open = false;
public ManualResetEvent(boolean open) {
this.open = open;
}
public void waitOne() throws InterruptedException {
synchronized (monitor) {
while (open==false) {
monitor.wait();
}
}
}
public boolean waitOne(long milliseconds) throws InterruptedException {
synchronized (monitor) {
if (open)
return true;
monitor.wait(milliseconds);
return open;
}
}
public void set() {//open start
synchronized (monitor) {
open = true;
monitor.notifyAll();
}
}
public void reset() {//close stop
open = false;
}
}

The closest I know of is the Semaphore. Just use it with a "permit" count of 1, and aquire/release will be pretty much the same as what you know from the ManualResetEvent.
A semaphore initialized to one, and
which is used such that it only has at
most one permit available, can serve
as a mutual exclusion lock. This is
more commonly known as a binary
semaphore, because it only has two
states: one permit available, or zero
permits available. When used in this
way, the binary semaphore has the
property (unlike many Lock
implementations), that the "lock" can
be released by a thread other than the
owner (as semaphores have no notion of
ownership). This can be useful in some
specialized contexts, such as deadlock
recovery.

Try CountDownLatch with count of one.
CountDownLatch startSignal = new CountDownLatch(1);

Based on:
ManualResetEvent allows threads to communicate with each other by
signaling. Typically, this
communication concerns a task which
one thread must complete before other
threads can proceed.
from here:
http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx
you possibly want to look at the Barriers in the Java concurrency package - specifically CyclicBarrier I believe:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/CyclicBarrier.html
It blocks a fixed number of threads until a particular event has occured. All the threads must come together at a barrier point.

I believe the crux of the .NET MRE is thread affinity and its ability to let all waiting threads go through when Set is called. I found the use of the Semaphore works well. However, if I get 10 or 15 threads waiting, then I run into another issue. Specifically, it occurs when Set is called. In .Net, all waiting threads are released. Using a semphore does not release all. So I wrapped it in a class. NOTE: I am very familiar with .NET threading. I am relatively new to Java threading and synchronization. Nevertheless, I am willing to jump in and get some real feedback. Here's my implementation with assumptions that a Java novice would make:
public class ManualEvent {
private final static int MAX_WAIT = 1000;
private final static String TAG = "ManualEvent";
private Semaphore semaphore = new Semaphore(MAX_WAIT, false);
private volatile boolean signaled = false;
public ManualEvent(boolean signaled) {
this.signaled = signaled;
if (!signaled) {
semaphore.drainPermits();
}
}
public boolean WaitOne() {
return WaitOne(Long.MAX_VALUE);
}
private volatile int count = 0;
public boolean WaitOne(long millis) {
boolean bRc = true;
if (signaled)
return true;
try {
++count;
if (count > MAX_WAIT) {
Log.w(TAG, "More requests than waits: " + String.valueOf(count));
}
Log.d(TAG, "ManualEvent WaitOne Entered");
bRc = semaphore.tryAcquire(millis, TimeUnit.MILLISECONDS);
Log.d(TAG, "ManualEvent WaitOne=" + String.valueOf(bRc));
}
catch (InterruptedException e) {
bRc = false;
}
finally {
--count;
}
Log.d(TAG, "ManualEvent WaitOne Exit");
return bRc;
}
public void Set() {
Log.d(TAG, "ManualEvent Set");
signaled = true;
semaphore.release(MAX_WAIT);
}
public void Reset() {
signaled = false;
//stop any new requests
int count = semaphore.drainPermits();
Log.d(TAG, "ManualEvent Reset: Permits drained=" + String.valueOf(count));
}
}
Also note that I am basically betting that there's no more than a 1000 requests waiting for a release at any given time. By releasing and aquiring in batches, I am attempting to release any waiting threads. Note the call to WaitOne is working 1 permit at a time.

Related

A semaphore which issues permits based on condition of permits already issued

I've code which calculates 3D surfaces by dividing the 3D domain into block and performs some relatively expensive operation on each block. I'm trying to parallelize it using a number of worker threads to processing the blocks. An important condition is that no two workers process adjacent blocks at the same time.
I've achieved a good amount of parallelization by dividing the domain into eight with each worker processing 1/8th of the domain and using a Semaphore to control access to the "danger zone" where two workers might conflict.
static final Semaphore available = new Semaphore(1, true);
class BoxGenerator implements Runnable {
...
void find_box(Box box) {
if(in_danger_zone(box)) {
try {
available.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
do_expensive_action(box);
if(in_danger_zone(box)) {
available.release();
}
}
}
What I would like to do is have a smarter method of issuing permits. Something like
for each current permit issued:
if safe_to_proceed(current_permit,box) the OK
else block
and hopefully use a higher level abstraction like Semaphore rather than having to ensure I get lower level code with wait() or Condition.await() correct.
A 2D permit might be to issue a permit if the x,y of the requested item is not within 1 of the coordinates of any current task.
Here is my first attempt, it solves the problem preventing conflicts, but all the locks degrade all the performance gains.
public class PermitIssuer<T> {
final BiPredicate<T,T> predicate;
final Collection<T> current ;
Lock lock = new ReentrantLock();
Condition hold = lock.newCondition();
public PermitIssuer(BiPredicate<T, T> predicate,int size) {
super();
this.predicate = predicate;
this.current = new ArrayBlockingQueue<T>(size);
}
boolean safeToIssuePermit(final T requester) {
boolean safe = current.stream().allMatch(t -> predicate.test(t,requester));
return safe;
}
public void aquire(final T requester) {
while(true) {
if(safeToIssuePermit(requester)) {
current.add(requester);
return;
}
lock.lock();
try {
hold.awaitUninterruptibly();
} finally {
lock.unlock();
}
}
}
public void release(final T requester) {
current.remove(requester);
lock.lock();
try {
hold.signalAll();
} finally {
lock.unlock();
}
}
}

Java optimized read/write a shared resource/memory location without Atomic API e.g. AtomicInteger

There is a shared resource and we need to perform read/write operations on it as per below:
When a write on resource is going on then no read should be allowed.
When a read is going on then no write should be allowed but multiple read threads should be able to read.
I have written code like mentioned below but the problem with this code is all reads will be blocked when a single read thread has acquired the lock. Further i am thinking to use a boolean flag e.g. canReadContinue. Now the first time when read acquires a lock i will flip this flag to true and if it is true then other threads should not try to acquire the lock.
class SharedResource {
Lock writeLock
public Object read() {
writeLock.acquire()
doRead()
}
public void write(Object toBeWritten) {
writeLock.acquire()
doWrite(toBeWritten)
writeLock.release()
}
}
Expected is multiple threads should be able to read when no write is going on.
UPDATED 1 :
public class SharedResource {
private Object writeLock = new Object();
private volatile boolean canReadContinue;
private volatile int readCount;
public void write(Object newState) throws InterruptedException {
synchronized (writeLock) {
// To make sure no read is going on
while (readCount > 0) {
wait();
}
System.out.println("Write thread has the lock.");
doWrite(newState);
}
}
public Object read() {
if(canReadContinue) {
incrementCount();
} else {
synchronized (writeLock) {
System.out.println("Read thread has the lock.");
canReadContinue = true;
incrementCount();
}
}
Object result = doRead();
decrementCount();
if(readCount == 0) {
// TODO - release lock and notify
}
return result;
}
private synchronized void incrementCount() {
readCount++;
}
private synchronized void decrementCount() {
readCount--;
}
private void doWrite(Object newState) {
// do stuff
}
private Object doRead() {
return "";
}
}
Now i need a mechanism to release the lock at line "// TODO - release lock and notify", any pointers how to resolve this issue ?
Hints:
You need a mutex; e.g. a primitive object lock.
You need a counter of the number of readers currently holding a logical read lock.
You need a flag to say if a writer is holding a logical write lock.
You hold the mutex if and only you are acquiring or releasing a logical lock. Once you have acquired it, you release the mutex.
You will need to use wait and notify.
Effectively you need to1 implement a simplified version ReadWriteLock.
1 - ... for the purposes of your homework assignment. In a real world program, you should simply use the existing ReadWriteLock class.
Answering on your updated code here is some skeleton for you to complete:
public class SharedResource {
private final Object signal = new Object();
private boolean writeLocked;
private int readerCount;
public void write(final Object newState) throws InterruptedException {
this.acquireWriteLock();
try {
// Now we know that no read and no other write is going on.
System.out.println("Write thread has the lock.");
this.doWrite(newState);
} finally {
// make sure we release the lock in any case.
this.realeaseWriteLock();
}
}
private void acquireWriteLock() throws InterruptedException {
synchronized (this.signal) {
// Wait until no more readers *and* no writer holds the lock.
// To do: Insert the condition we need to wait for:
while (/* condition here! */ ) {
// To do: Wait for the lock-holding thread(s) to signal that they released their lock(s).
}
this.writeLocked = true; // Let others know that the write lock has been taken.
}
}
private void realeaseWriteLock() {
synchronized (this.signal) {
this.writeLocked = false;
// To do: Notify any and all other waiting threads that we released the lock!
}
}
public Object read() {
// To be done...
}
private void acquireReadLock() throws InterruptedException {
synchronized (this.signal) {
// Wait until no *writer* holds the lock.
// To do: Insert condition we need to wait for:
while (/* condition here! */ ) {
// To do: Wait for the lock-holding thread(s) to signal that they released their lock(s).
}
// Now we know that no writer holds the lock. Acquire (another) read lock:
this.readerCount++;
}
}
private void releaseReadLock() throws InterruptedException {
synchronized (this.signal) {
this.readerCount--;
// To do: Notify any threads waiting (i.e. writer threads).
// (In fact only *required* if there are *no* more readers now because that's the only condition any thread will wait on.)
}
}
private void doWrite(final Object newState) {
// do stuff
}
private Object doRead() {
return "";
}
}
The main point to understand may be that every attempt to take a lock may have to wait, and that every release of a lock should notify any (potential) waiting threads.
Further i am thinking to use a boolean flag e.g. canReadContinue
You're on the right track. But remember that any number of threads could concurrently perform their read accesses and that the write access can only be done if no other thread is currently reading or writing.
So you need to keep track of how many readers are currently holding the lock, and every reader must make sure to release the lock when it's done. Only if & when 0 readers (and 0 writers) hold the lock, a writer may proceed; and only if & when 0 writers hold the lock, any reader may proceed.

Java - Synchronized but allow one method to be accessed by different threads

In the example below:
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
inc1 and inc2 can be accessed at the same time, but neither can be accessed by multiple threads at the same time.
How would it be possible to allow only inc1 or inc2 to be accessed whilst the other is like regular syncing however allowing the one that is being accessed to be done so by as many threads as possible.
I think a useful analogy is traffic passing through an intersection, where you can have multiple cars sharing one road, as long as they're driving in parallel. The challenge is finding a coordination strategy for intersecting traffic.
The solution proposed by #Greg works if traffic is intermittent and we can wait for one stream to stop before allowing the intersecting stream to proceed. But I suspect that's not very realistic. If there's steady traffic on one road, the rest of the cars will wait forever, a.k.a. thread starvation.
An alternative strategy is to allow cars to cross on a first come, first served basis, like at a stop sign. We can implement that using a dedicated semaphore for each "road", or segment, where each user takes a permit, after first making sure none of the other segments have permits in use:
public class StopSign {
private final Semaphore[] locks;
private volatile int current = 0;
public StopSign(int segments) {
// create and populate lock array, leaving
// all segments drained besides the first
locks = new Semaphore[segments];
Arrays.setAll(locks, i -> new Semaphore(i == 0 ? Integer.MAX_VALUE : 0, true));
}
public void enter(int segment) {
// synchronization is necessary to guard `current`,
// with the added benefit of holding up new threads
// in the active segment while we're gathering permits
synchronized (locks) {
if (segment == current) {
// if our segment is active, acquire a permit
locks[segment].acquireUninterruptibly();
} else {
// otherwise, gather all permits from the active segment
// as they become available and then reclaim our own permits
locks[current].acquireUninterruptibly(Integer.MAX_VALUE);
current = segment;
locks[segment].release(Integer.MAX_VALUE - 1);
}
}
}
public void exit(int segment) {
if (segment != current) {
// we don't own the lock!
throw new IllegalMonitorStateException();
}
locks[segment].release();
}
}
To use the class, we simply call enter(i) and exit(i), where i identifies the road/segment/method we want to use. Here's a demo using 3 segments:
public static void main(String args[]) {
int segments = 3;
StopSign lock = new StopSign(segments);
IntStream.range(0, segments).parallel().forEach(i -> {
for (int j = 0; j < 10; j++) {
lock.enter(i);
System.out.print(i);
lock.exit(i);
sleepUninterruptibly(20, TimeUnit.MILLISECONDS);
}
});
}
A test run on my machine produces this alternating pattern:
120201210012012210102120021021
This strategy could make sense if traffic is relatively light, but in heavy traffic the overhead of coordinating each crossing can significantly restrict throughput. For busy intersections, you'll usually want a traffic light, or a third party that can transfer control at a reasonable frequency. Here's an implementation of a such a concept, using a background thread that manages a set of read/write locks, making sure only one segment has a write lock available at a time:
public class TrafficLight {
private final ReadWriteLock[] locks;
private final Thread changer;
public TrafficLight(int segments, long changeFrequency, TimeUnit unit) {
// create and populate lock array
locks = new ReadWriteLock[segments];
Arrays.setAll(locks, i -> new ReentrantReadWriteLock(true));
CountDownLatch initialized = new CountDownLatch(1);
changer = new Thread(() -> {
// lock every segment besides the first
for (int i = 1; i < locks.length; i++) {
locks[i].writeLock().lock();
}
initialized.countDown();
int current = 0;
try {
while (true) {
unit.sleep(changeFrequency);
// lock the current segment and cycle to the next
locks[current].writeLock().lock();
current = (current + 1) % locks.length;
locks[current].writeLock().unlock();
}
} catch (InterruptedException e) {}
});
changer.setDaemon(true);
changer.start();
// wait for the locks to be initialized
awaitUninterruptibly(initialized);
}
public void enter(int segment) {
locks[segment].readLock().lock();
}
public void exit(int segment) {
locks[segment].readLock().unlock();
}
public void shutdown() {
changer.interrupt();
}
}
Now let's tweak the test code:
TrafficLight lock = new TrafficLight(segments, 100, TimeUnit.MILLISECONDS);
The result is an orderly pattern:
000111112222200000111112222200
Notes:
awaitUninterruptibly() and sleepUninterruptibly() are Guava helper methods to avoid handling InterruptedException. Feel free to copy the implementation if you don't want to import the library.
TrafficLight could be implemented by delegating state management to visiting threads, instead of relying on a background thread. This implementation is simpler (I think), but it does have some extra overhead and it requires a shutdown() to be garbage collected.
The test code uses parallel streams for convenience, but depending on your environment, it may not interleave very well. You can always use proper threads instead.
You could keep track of what mode you're in, and how many operations of that type are in progress, then only flip the mode when all of those operations are complete, eg:
public class MsLunch {
private enum LockMode {IDLE, C1_ACTIVE, C2_ACTIVE};
private LockMode lockMode = IDLE:
private int activeThreads = 0;
private long c1 = 0;
private long c2 = 0;
public void inc1() {
try {
enterMode(C1_ACTIVE);
c1++
} finally {
exitMode();
}
}
public void inc2() {
try {
enterMode(C2_ACTIVE);
c2++
} finally {
exitMode();
}
}
private synchronized void enterMode(LockMode newMode){
while(mode != IDLE && mode != newMode) {
try {
this.wait(); // don't continue while threads are busy in the other mode
} catch(InterruptedException e) {}
}
mode = newMode;
activeThreads++;
}
private synchronized void exitMode(){
activeThreads--;
if (activeThreads == 0) {
mode = IDLE;
this.notifyAll(); // no more threads in this mode, wake up anything waiting
}
}
}

Not wait in case synchronized section is occupied [duplicate]

This question already has answers here:
How do determine if an object is locked (synchronized) so not to block in Java?
(8 answers)
Closed 6 years ago.
I have synchronisation block in syncCmd function:
public Object Sync = new Object();
public void syncCmd(String controlCmd) {
synchronized(Sync) {
...
}
}
I need to add some logic in case if one thread has occupied Sync and doing its job. In this case I would like to report "too busy" to system and not get to queue. What is the best way to know if somebody has occupied Sync section? How to know how many threads is waiting in this section? Everything is in Java 1.4.
Have a look at the Lock interface and its implementation ReentrantLock. It allows you to use tryLock() method, including the variant that allows to wait for some time if the resource is already locked:
private ReentrantLock lock = new ReentrantLock();
public void syncCmd(String controlCmd) {
if (lock.tryLock()) {
try {
// Use your synchronized resource here
} finally {
lock.unlock();
}
} else {
// Failed to lock
}
}
Java 1.4, unfortunately, has no java.util.concurrency package and I think the best choice you have is to implement the same logic by means of synchronized and double checks:
public class Lock {
private final Object lock = new Object();
private volatile boolean locked = false;
public boolean tryLock() {
if (!locked) {
synchronized (lock) {
if (!locked) {
locked = true;
return true;
}
}
}
return false;
}
public void unlock() {
synchronized (lock) {
locked = false;
}
}
}
It will not work as fast as ReentrantLock that uses CAS loop backed by processor instructions in modern JVMs, but it will do the job.
This implementation is also not reentrant, you can extend it to track the locking thread and locks count if you need reentrance.
Important update: #Stephen C made a good point that double check is broken in Java 1.4 and one always must keep it in mind. But there're exceptions. For instance, short primitive types. So, I think it will work in this particular case. For more details, please, look at the "Double-Checked Locking is Broken" Declaration.
Synchronized blocks / methods and primitive mutexes can't do that in Java.
But if you use a Lock instead (javadoc), you can use tryLock either to never block or to only block for a limited time.
Example:
Lock l = new ReentrantLock();
if (l.tryLock()) {
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
else {
// report "too busy"
}
But note that it is essential to use "try ... finally" and an explicit unlock() call to ensure that the lock is always released. (Unlike the synchronized constructs, which takes care of that for you automatically.)
Prior to Java 1.5 there is no solution that I am aware of in pure Java. It might be possible with native code trickery, but I don't know how.
You / your management should be looking to ditch support in your products for Java 1.4, and to migrating away from any third-party product that depends on top of it. Java 1.5 itself was EOL'd many years ago. In fact, all releases prior to Java 1.8 have been EOL'd; see the Oracle Java SE Support Roadmap document.
Two of the answers above talked about java.util.concurrent.locks.ReentrantLock, but it doesn't exist in Java 1.4.
Too bad so sad?
No! If system libraries and 3rd party libraries don't hand you what you want, then write it yourself!
The code below does what you asked for, and absolutely nothing more. I personally would not use it without first adding some features that would make it more useable, more testable, and most importantly, more foolproof.
I'm just offering it to you as an example of where to begin.
public class ExtremelySimplisticNonReentrantLock {
boolean isLocked = false;
/**
* #return true if the lock was acquired, false otherwise.
*/
public synchronized boolean tryToAcquire() {
if (isLocked) {
return false;
}
isLocked = true;
return true;
}
public synchronized void release() {
lsLocked = false;
}
}
Share and Enjoy!
Try this (Two classes - Executor and Tracker ) :
Executor :
package com.example.so.jdk1_4.synch;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
* <p> For http://stackoverflow.com/questions/38671520/not-wait-in-case-synchronized-section-is-occupied </p>
* #author Ravindra HV
*/
public class InUseExample {
public synchronized void execute(String command) {
InUseTracker.obtainClassInstance().setInuse(true);
try {
System.out.println("Executing :"+command);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}// do work
InUseTracker.obtainClassInstance().setInuse(false);
}
/**
* #param args
*/
public static void main(String[] args) {
System.out.println("Start :"+new Date());
testInUseExample();
System.out.println("Final wait count :"+InUseTracker.obtainClassInstance().waitCount());
System.out.println("End :"+new Date());
}
private static void testInUseExample() {
final InUseExample inUseExample = new InUseExample();
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
InUseTracker.obtainClassInstance().incrementWaitCount();
while(true) {
if( InUseTracker.obtainClassInstance().isInuse() == false ) { // reduces the chances of this thread going to a block mode..
inUseExample.execute(Thread.currentThread().getName());
break;
}
else {
try {
Random random = new Random();
String message = Thread.currentThread().getName()+" - block in use by :"+InUseTracker.obtainClassInstance().getInUseBy();
message = message+" "+". Wait Count :"+InUseTracker.obtainClassInstance().waitCount();
System.out.println(message);
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
InUseTracker.obtainClassInstance().decrementWaitCount();
}
}
};
int threadCount = 10;
List<Thread> threadPoolTemp = new ArrayList<Thread>();
for(int i=0;i<threadCount;i++) {
Thread thread = new Thread(runnable);
threadPoolTemp.add(thread);
}
for (Thread thread : threadPoolTemp) {
thread.start();
}
for (Thread thread : threadPoolTemp) {
try {
thread.join(); // wait until all threads have executed..
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Tracker :
package com.example.so.jdk1_4.synch;
/**
* <p> For http://stackoverflow.com/questions/38671520/not-wait-in-case-synchronized-section-is-occupied </p>
* #author Ravindra HV
*/
public class InUseTracker {
private boolean inuse;
private int waitCount;
private String inUseBy;
private static InUseTracker DEFAULT_INSTANCE = new InUseTracker();
private InUseTracker() {
}
public static InUseTracker obtainClassInstance() {
return DEFAULT_INSTANCE;
}
public synchronized boolean isInuse() {
return inuse;
}
public synchronized void setInuse(boolean inuse) {
this.inuse = inuse;
if(inuse) {
setInUseBy(Thread.currentThread().getName());
}
else {
setInUseBy("");
}
}
private void setInUseBy(String inUseBy) {
this.inUseBy = inUseBy;
}
public synchronized String getInUseBy() {
return inUseBy;
}
public synchronized void incrementWaitCount() {
waitCount++;
}
public synchronized void decrementWaitCount() {
waitCount--;
}
public synchronized int waitCount() {
return waitCount;
}
}
PS: Guess you'd have to move the
InUseTracker.obtainClassInstance().setInuse(false);
within a finally if or as appropriate.

Java Concurrent Collection Search

I've been programming in Java for sometime but new to concurrent programming, so bear with me!
I'm trying to develop a class that holds a group of Collection classes [eg ArrayLists] and then to find a specified value it traverses all collections at the same time, stopping all threads if it finds the given value.
I've pasted my code below and was wondering if anyone knows how within contains_multiple_collections() I catch if one of the threads returned Futures has returned true?
Thanks
Graham
public class CollectionGroup<V> extends ContainerGroup
{
//...
public boolean contains(V value)
{
boolean containsValue = false;
if (mCollections.size() == 1)
{
containsValue = mCollections.get(0).contains(value);
}
else
{
containsValue = contains_multiple_collections(value);
}
return containsValue;
}
private boolean contains_multiple_collections(V value)
{
// thread pool
int numberProcessors = mCollections.size();
ExecutorService es = Executors.newFixedThreadPool(numberProcessors);
for (int i=0; i<numberProcessors; i++)
{
AbstractCollection<V> collection = mCollections.get(i);
MyCallable callable = new MyCallable(collection,value);
Future<Boolean> future = es.submit(callable);
//...
}
return true;
}
private class MyCallable implements Callable<Boolean>
{
protected AbstractCollection<V> mCollection;
protected V mValue;
public MyCallable(AbstractCollection<V> collection, V value)
{
mCollection = collection;
mValue = value;
}
#Override
public Boolean call() throws Exception
{
boolean ok = mCollection.contains(mValue);
return ok;
}
} // class MyCallable
} // class CollectionGroup
contains won't stop just because you might have found the value in another thread. The only way to do this is to loop yourself.
For a CPU intensive process, the optimal number of threads is likely to be the number of cores you have. Creating too many threads adds overhead which slows down your solution.
You should also remember to shutdown() the ExecutorService when you are finished with it.
If you want to speed up the search, I would maintain a Set of all values this is likely to be 10-100x faster than using multiple threads.
You could use an ExecutorCompletionService. Just keep take()ing (take() blocks until a completed Future is present) until you get a result that is true and shutdownNow() the underlying ExecturService once you've found something. This won't immediately stop all threads once a value is found though.
The issue is that your contains_multiple_collections method does not wait for the search to complete. You have two options I can think of. The first would involve some asynchronous callback implementation where the contains method does not block and perhaps takes a callback/listener object as an argument. The second is to make the contains method block until an outcome has been determined. I've outlined a sample implementation for latter approach below, it's not tested so be careful...
/*
* contains_multiple_collections now blocks until the desired
* value is located or all searches have completed unsuccessfully...
*/
private boolean contains_multiple_collections(V value) {
// thread pool
int numberProcessors = mCollections.size();
ExecutorService es = Executors.newFixedThreadPool(numberProcessors);
Object lock = new Object();
AtomicBoolean outcome = new AtomicBoolean(false);
AtomicInteger remainingSearches = new AtomicInteger(mCollections.size());
for (int i = 0; i < numberProcessors; i++) {
AbstractCollection<V> collection = mCollections.get(i);
es.submit(new MyRunnable(collection, value, lock, outcome, remainingSearches));
}
/* Wait for searches to run. This thread will be notified when all searches
* complete without successfully locating the value or as soon as the
* desired value is found.
*/
synchronized (lock) {
while (!outcome.get() && remainingSearches.get() > 0) {
try {
lock.wait();
} catch (InterruptedException ex) {
// do something sensible.
}
}
es.shutdownNow();
}
return outcome.get();
}
private class MyRunnable implements Runnable {
final AbstractCollection<V> mCollection;
final V mValue;
final Object lock;
final AtomicBoolean outcome;
final AtomicInteger remainingSearches;
public MyRunnable(AbstractCollection<V> mCollection, V mValue,
Object lock, AtomicBoolean outcome, AtomicInteger remainingSearches) {
this.mCollection = mCollection;
this.mValue = mValue;
this.lock = lock;
this.outcome = outcome;
this.remainingSearches = remainingSearches;
}
public void run() {
boolean ok = mCollection.contains(mValue);
if (ok || remainingSearches.decrementAndGet() == 0) {
synchronized (lock) {
if (ok) {
outcome.set(true);
}
lock.notify();
}
}
}
}
You could repeatedly loop through all the futures and poll them with get, using zero or almost zero timeout, but probably a better idea is to provide a callback to all your MyCallables, which should then call it when a match is found. The callback should then cancel all other tasks, maybe by shutting down the ExecutorService.
I suggest using a static AtomicBoolean which is set when a match is found. Each thread could then check the value before proceeding.

Categories