2012-10-24 28 views
0

我們有一個計劃任務,每10秒運行一個線程池,其中包含3個線程,可以實際更新靜態通用映射。計劃的操作每10秒鐘打印一次該地圖。 問題是我希望計劃程序在3個線程完成地圖後停止打印。但這裏是關鍵。我不想立即停止調度程序,我想先打印(地圖的最終版本),然後完成。進行預定的調用以運行一次更多時間

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? 
     } 
    } 
} 

Listener實際上只是在線程完成時得到通知。

回答

1

首先,使numberOfThreads同步。兩個Reader線程併發完成時,您不希望它損壞。這是一個原始的int,因此可能不會被破壞(我對JVM不太熟練),但是無論如何應該遵循線程安全的一般規則。

// 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 

但是,這當然不應該直接從notifyRunnableComplete調用。監聽器方法從你的Reader線程中調用,所以它會阻塞3個線程中的最後一個線程及時完成。而是讓一些其他線程將會在wait()上的通知對象(最好是執行getAnswer()的那個),notify()它在numberOfThreads達到3時將上面的代碼放在wait()之後。

哦,並且當wait()取消阻止時,您應該仔細檢查numberOfThreads是否真的爲3,如果不是,則循環回到wait()。谷歌「虛假喚醒」來解釋爲什麼這是必要的。

相關問題