2012-08-28 27 views
0

我有一個主進程main。它創建10個線程(說),然後我想做的事是:在線程上調用不同的方法

while(required){ 
Thread t= new Thread(new ClassImplementingRunnable()); 
t.start(); 
counter++; 
} 

現在我有這些線程的列表,併爲每個線程我想要做的一組過程中,同樣爲所有,因此我把這個實現放在ClassImplementingRunnable的運行方法中。

現在線程完成它們的執行後,我想等所有的人停下來,然後再次喚起它們,但是這次我想不是並行地連續執行它們。

爲此,我加入每個線程,等待它們完成執行,但之後我不知道如何再次喚起它們並連續運行那段代碼。 我可以這樣做

for(each thread){ 
t.reevoke(); //how can i do that. 
t.doThis(); // Also where does `dothis()` go, given that my ClassImplementingRunnable is an inner class. 
} 

而且,我想使用同一個線程,也就是我想從他們離開的地方繼續,但以串行方式。 我不知道如何去了解最後一塊僞代碼。 請幫忙。 使用java。

+0

所以你想測試是否更快地啓動所有線程在同一時間(並行)與連續啓動它們? – brimborium

+0

什麼是'doThis'?它是否引用Runnables的run方法? – assylias

+2

'這次我想串行地並行處理它們。「在這種情況下,你不需要多線程,你只需要一個線程就可以調用線程。完成後,您無法重新啓動線程。 –

回答

3

不能重新啓動一個線程。

你可以做的是使用java.util.concurrent包等待線程完成並重新運行您可運行在主線程按順序運行它們 - 把你的可運行在列表中,您可以在訪問它們順序運行。

ExecutorService executor = Executors.newFixedThreadPool(10); 
List<Runnable> runnables = new ArrayList<Runnable>(); 

for (int i = 0; i < 10; i++) { 
    Runnable r = new ClassImplementingRunnable(); 
    runnables.add(r); 
    executor.submit(r); 
} 

executor.shutdown(); 
//wait until all tasks are finished 
executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); 

//re run the tasks sequentially 
for (ClassImplementingRunnable r : runnables) { 
    //the method below can access some variable in 
    //your ClassImplementingRunnable object, that was 
    //set during the first parallel run 
    r.doSomethingElse(); 
} 
+0

這個答案勝過我的,因爲它敦促切換到執行程序並顯示實現它所需的實際代碼。通過這種方法,可以通過使用Callable來改進解決方案,並立即開始打印Future.get()的結果,在等待任務完成時根據需要進行阻塞。 –

3

如果你想串行執行,只是使用

for (int i = 0; i < 10; i++) 
    new ClassImplementingRunnable().run(); 

所有的任務都在同一個線程中運行,一前一後。這是實現你想要的最乾淨的方式。

更新

您的評論後,很明顯,你其實不想再次運行相同的任務,但打印他們計算的結果。這將更加簡單:

  1. ClassImplementingRunnable實例添加到任務列表中;
  2. 在自己的線程中運行每個任務;
  3. 加入所有的線程;
  4. 編寫一個for循環,打印每個ClassImplementingRunnable實例的結果。

你已經有2個和3

+0

說,我的第一個線程創建了一些列表,第二個線程也是如此,但所有的數據都是不同的。現在如果我想打印這些數據,如果我只將這種打印的東西放在run方法中,它會給我造成奇怪的結果,因爲它們都會互相干擾。 – Kraken

+0

和你建議的方式,我不認爲我將能夠記住每個線程停止的狀態。或者我會嗎? – Kraken

+0

然後你還沒有明確你的要求。一旦你運行了一個任務,再次運行完全相同的任務是沒有意義的。如果你想打印結果,這與計算結果不同。你需要的僅僅是一個簡單的'for'循環,它讀取由這些任務計算的列表並打印它們。 –

0

我猜你想要的東西像 ExecutorCompletionService

來自實例Java文檔複製。

用法示例。假設你有一套針對某個問題的求解器,每個都返回一個Result類型的值,並且想要併發地運行它們,在某些方法中使用(處理每個返回非空值的結果)結果r)。你可以這樣寫:

void solve(Executor e, 
      Collection<Callable<Result>> solvers) 
throws InterruptedException, ExecutionException { 
    CompletionService<Result> ecs 
     = new ExecutorCompletionService<Result>(e); 
    for (Callable<Result> s : solvers) 
     ecs.submit(s); 
    int n = solvers.size(); 
    for (int i = 0; i < n; ++i) { 
     Result r = ecs.take().get(); 
     if (r != null) 
      use(r); 
    } 

}

0

雖然這裏有一些很好的答案,但我不確定您最初的問題是否已被回答。

現在線程完成它們的執行之後,我要等所有的人停下來,然後再次喚起它們,但是這次我想以並行方式連續執行它們。

您正混淆來自其對象的運行線程。這是一個非常常見的模式(儘管通常由與ExecutiveService類更好)做類似如下:

List<ClassExtendingThread> threads = new ArrayList<ClassExtendingThread>(); 
// create your list of objects 
for (int i = 0; i < 10; i++) { 
    ClassExtendingThread thread = new ClassExtendingThread(...); 
    thread.start(); 
    threads.add(thread); 
} 

for (ClassExtendingThread thread : threads) { 
    // now wait for each of them to finish in turn 
    thread.join(); 
    // call some method on them to get their results 
    thread.doThis(); 
} 

請注意,我改變了你的類擴展Thread。像你一樣實施Runnable通常會更好,但是如果您打算加入並回撥對象,則擴展Thread會使代碼更容易。

因此,您創建對象實例,將它們作爲線程啓動,然後與它們一起join(),它們都等待它們完成並同步它們的內存。一旦你用線程join(),你可以調用你想要的對象上的任何方法。那根本不會「重新喚起」線程。它只是訪問你的對象內的字段。如果您在線程運行時嘗試這樣做,那麼您需要擔心synchronization

相關問題