2012-09-20 25 views
4

我有以下形式的螺紋:如何在Java中設置以下線程?

  1. 每個線程的每個執行應該運行在類的功能。該功能本身是完全安全的。該函數返回一個值,比如int。

  2. 所有線程都被執行後,函數值需要積累。

所以,它會(在僞代碼)類似的東西:

a = 0 
    for each i between 1 to N 
     spawn a thread independently and call the command v = f(i) 
     when thread finishes, do safely: a = a + v 
    end 

我不知道如何在這種情況下使用Java。

問題不在於創建線程,我知道這可以用

問題積累所有的答案來完成。

感謝您的任何信息。

+0

與Java沒有太多的經驗,但我建議您查看從Java .. 7 ForkJoin東西?我覺得是這樣的。試試這個:http://www.infoq。com/news/2008/03/fork_join – adelbertc

回答

4

我可能會做這樣的事情:

public class Main { 
    int a = 0; 
    int[] values; 
    int[] results; 

    public Main() { 
     // Init values array 

     results = new int[N]; 
    } 

    public int doStuff() { 
     LinkedList<Thread> threads = new LinkedList<Thread>(); 

     for (final int i : values) { 
      Thread t = new Thread() { 
       public void run() { 
        accumulate(foo(i)); 
       } 
      }; 

      threads.add(t); 
      t.start(); 
      } 

      for (Thread t : threads) { 
       try { 
        t.join(); 
       } catch (InterruptedException e) { 
        // Act accordingly, maybe ignore? 
       } 
      } 

      return a; 
    } 

    synchronized void accumulate(int v) { 
      // Synchronized because a += v is actually 
      // tmp = a + v; 
      // a = tmp; 
      // which can cause a race condition AFAIK 
      a += v; 
    } 
} 
+0

你的想法很好。記住面向接口的代碼,使用'List threads = new ClassThatImplementsList ();'而不是聲明'LinkedList'。 –

+0

感謝您的提示! =) –

3

使用的ExecutorCompletionServiceExecutorCallable

開始用Callable調用您int功能:

public class MyCallable implements Callable<Integer> { 
    private final int i; 

    public MyCallable(int i) { 
     this.i = i; 
    } 

    public Integer call() { 
     return Integer.valueOf(myFunction(i)); 
    } 
} 

創建一個Executor

private final Executor executor = Executors.newFixedThreadPool(10); 

10是一次執行的最大線程數。

然後把它包在ExecutorCompletionService和提交作業:

CompletionService<Integer> compService = new ExecutionCompletionService<Integer>(executor); 

// Make sure to track the number of jobs you submit 
int jobCount; 
for (int i = 0; i < n; i++) { 
    compService.submit(new MyCallable(i)); 
    jobCount++; 
} 

// Get the results 
int a = 0; 
for (int i = 0; i < jobCount; i++) { 
    a += compService.take().get().intValue(); 
} 

ExecutorCompletionService讓你拉斷的任務隊列,因爲他們完成。這與加入線程有點不同。雖然總體結果是相同的,但如果要在線程完成時更新UI,則無法知道線程將使用連接完成的順序。這最後for循環可能是這樣的:

for (int i = 0; i < jobCount; i++) { 
    a += compService.take().get().intValue(); 
    updateUi(a); 
} 

,這將更新UI爲完成任務。使用Thread.join不一定會做,因爲你會得到結果的順序來調用連接,的順序線程完成。

通過使用該執行的,這也將讓你限制你在給定的時間運行並行作業的數量,以便你不小心線程彈系統。

+0

當然,如果你不需要在你的代碼中更新除'a'之外的任何東西,那麼使用'Thread.join'就可以了:) – Brian

+0

+1對於使用恰當的工具 –

相關問題