Question

I have a program which is listening for random numbers. It is hooked up to a publisher which gives me a number and a new count and every time I get an update, I'm storing the current count for that number in a HashMap.

I also have an SSL server listening for requests. When a request comes in asking "how many 7's do we have" I just return the value in my HashMap.

Now I want to add logic that says, if we have 0 occurrences of that number, wait until we get one, and return the count at that point. However I'm struggling because of the limitation on the Thread's run method, that it must be a void. I wonder if there is anyway to just declare my method as one that always launches a new thread, or maybe a better way to handle it than what I am doing. Here is what I have:

private static volatile HashMap<Integer, Integer> occurenceMap= new HashMap<Integer, Integer>();

public synchronized static int getNumOccurrences(final Integer number) {

    try { 
    (new Thread() {

        public void run() {

            Integer occurrences = occurenceMap.get(number); 
            if ( occurrences != null && occurrences > 0 ) {
              // here I would like to just return occurences;
            } else {
                CountDownLatch latch = new CountDownLatch(1); 
                pendingList.put(number, latch);
                latch.await();  
                // elsewhere in the code, I call countdown when I get a hit
                pendingList.remove(number);

                // once we've counted down, I would like to return the value
             }
           }
       }).start();
   } catch ( Throwable t ) { }
}

However, I can't put return statements in the run method. So how is this best done?

Thank you!

Was it helpful?

Solution

You'd need some kind of external structure to store the number, like this

// declared outside your runnable
final AtomicInteger result = new AtomicInteger(0);

// in your run method
// return value; // doesn't work, can't return
result.set(value);

So adding it into yours, you get this

Note that my comments start with // C:

private static volatile HashMap<Integer, Integer> occurenceMap= new HashMap<Integer, Integer>();


    public synchronized static int getNumOccurrences(final Integer number) {
        // C: here's a container to use inside the runnable
        // C: must be final to use inside the runnable below
        final AtomicInteger result = new AtomicInteger(0);
        try { 
        // C: keep a rerefence to the thread we create
        Thread thread = new Thread() {

            public void run() {

                Integer occurrences = occurenceMap.get(number); 
                if ( occurrences != null && occurrences > 0 ) {
                    result.set(occurences); // C: we found what we're looking for
                    return; // C: so get out of the run method
                } else {
                    CountDownLatch latch = new CountDownLatch(1); 
                    pendingList.put(number, latch);
                    latch.await();  
                    // elsewhere in the code, I call countdown when I get a hit
                    pendingList.remove(number);

                    // once we've counted down, I would like to return the value
                    result.set(1); // C: I'm not sure what you want to return here
                    return; // C: but I'm sure you can figure that out...
                 }
               }
           });
           thread.start(); // C: now start the thread
           thread.join(); // C: join the thread, waiting for it to finish
       } catch ( Throwable t ) { }
       return result.get(); // C: now return the int from the container
    }

OTHER TIPS

Another way to result values from your Thread execution it is to use the Executors thread-pools which allow you to submit a Callable:

// create a thread pool with 10 workers
ExecutorService threadPool = Executors.newFixedThreadPool(10);
List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
for (Job job : jobsToDo) {
    futures.add(threadPool.submit(new Callable<Integer>() {
       public Integer call() {
          ...
       }
     }));
}
// after submitting the jobs, you need to shutdown the queue
threadPool.shutdown();
// then you can get the results
for (Future<Integer> future : futures) {
    // this will throw if your call method throws
    int value = future.get();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top