Manos
Manos

Reputation: 151

Make a Scheduled Call to run One More time

We have a scheduled task that runs every 10 seconds and a thread pool with 3 threads that actually update a static common map. Every 10 seconds the scheduled action prints this map. The problem is that I want the scheduler to stop printing after the 3 threads finish with the map. But here is the key. I don't want to stop scheduler instantly, I want to print first ( the final version of the map) and then finishes.

public class myClass implements ThreadListener {
    public static ArrayList<Pair<String, Integer>> wordOccurenceSet = new ArrayList<Pair<String, Integer>>();
    int numberOfThreads = 0;
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    public void getAnswer(Collection<CharacterReader> characterReaders, Outputter outputter) {




        ExecutorService executor = Executors.newFixedThreadPool(characterReaders.size());
         OutputterWriteBatch scheduledThread = new OutputterWriteBatch(outputter,wordOccurenceSet);

        scheduler.scheduleAtFixedRate(scheduledThread, 10, 10, TimeUnit.SECONDS);
        for (CharacterReader characterReader : characterReaders) {
            NotifyingRunnable runnable = new CharacterReaderTask(characterReader, wordOccurenceSet);
            runnable.addListener(this);

            executor.execute(runnable);
        }



    }


    @Override
    public void notifyRunnableComplete(Runnable runnable) {
        numberOfThreads += 1;
        if(numberOfThreads == 3 ){
         //All threads finished...  What can I do to terminate after one more run?
        }
    }
}

The Listener actually just get notified when a thread finishes.

Upvotes: 0

Views: 80

Answers (1)

Pavel Zdenek
Pavel Zdenek

Reputation: 7278

First of all, make your numberOfThreads synchronized. You don't want it to become corrupted when two Reader threads finish concurrently. It's a primitive int so it may not be corruptable (i am not that proficient with JVM), but the general rules of thread safety should be followed anyway.

// 1. let finish OutputterWriteBatch if currently running
scheduler.shutdown(); 
// 2. will block and wait if OutputterWriteBatch was currently running
scheduler.awaitTermination(someReasonableTimeout);
// 3. one more shot.
scheduler.schedule(scheduledThread,0);
// You could also run it directly if your outputting logic in run()
// is published via separate method, but i don't know the API so i suppose
// only Runnable is published

But this shouldn't be called directly from notifyRunnableComplete, of course. The listener method is called from your Reader threads, so it would block the last one of 3 threads from finishing timely. Rather make a notification object which some other thread will wait() on (preferably the one which executed getAnswer()), notify() it when numberOfThreads reaches 3 and put the above code after the wait().

Oh, and when wait() unblocks, you should double check that numberOfThreads is really 3, if not, cycle back to wait(). Google "spurious wakeup" to explanation why this is needed.

Upvotes: 1

Related Questions