2013-11-14 24 views
1

我正在開發一個Java應用程序,用於計算數字的權力。我想利用我的四核電腦,因爲只有一個核心正在使用這個應用程序。我已經看過關於如何同步線程的不同教程,但我並不真正瞭解它。我的代碼如下:如何將數學工作分解爲工作線程Java

public class Bignum{ 

public static void main(String[] args){ 

    Random generator = new Random(); 
    long start = System.nanoTime(); 
    Random generator1 = new Random(); 

for (long i=0; i<9000;i++){ 

    int power = generator1.nextInt (17) + 2; 
    int power1 = generator1.nextInt (25) + 2; 
    int power2 = generator1.nextInt (72) + 2; 

    BigInteger num = BigInteger.valueOf (generator.nextInt (7895) + 1); 
    BigInteger num1 = BigInteger.valueOf (generator.nextInt (1250) + 1); 
    BigInteger num2 = BigInteger.valueOf (generator.nextInt (9765) + 1); 

    BigInteger add = num.pow(power); 
    BigInteger add1 = num1.pow(power1); 
    BigInteger add2 = num2.pow(power2); 

    BigInteger sum = add.add(add1); 

} 

} 
} 

因此,舉例來說,我怎麼可能有一個線程做到這一點:

int power = generator1.nextInt (17) + 2; 
    int power1 = generator1.nextInt (25) + 2; 
    int power2 = generator1.nextInt (72) + 2; 

另一個做到這一點:

BigInteger num = BigInteger.valueOf (generator.nextInt (7895) + 1); 
    BigInteger num1 = BigInteger.valueOf (generator.nextInt (1250) + 1); 
    BigInteger num2 = BigInteger.valueOf (generator.nextInt (9765) + 1); 

另一個這樣的:

BigInteger add = num.pow(power); 
    BigInteger add1 = num1.pow(power1); 
    BigInteger add2 = num2.pow(power2); 

而最後一個這樣做:

BigInteger sum = add.add(add1); 

我該怎麼做?另外,我怎麼還能重複那9000次?感謝您的幫助。

+0

我認爲最好是在不同的線程中運行每一個,而不是每個步驟。那麼你同步,直到所有完成並添加 –

+1

那麼你基本上不會操作太小。設置線程所花費的時間要比活着的時間長得多。三個線程每個進行3000次迭代都是有意義的。 –

+0

@TonyHopkinson你能告訴我我該怎麼做? – hichris123

回答

2

所以我真的推薦this book開始使用java多線程。這就像這個東西的聖經。

這就是說,你將需要一個線程池來保存你的任務,並且你需要創建一個處理它需要做什麼的'worker'類(它將成爲線程),並且正確退出/返回它的價值。

- 製作你的線程池

ExecutorService executor = Executors.newFixedThreadPool(MAX_NUMBER_THREADS_AT_ONCE); 

- 製作你的工人的任務

public static class WorkerTask implements Runnable { 
    //member vars if you need em 

    WorkerTask() { 
     //initialize member vars if you need to 
    } 

    @Override 
    public void run() { 
      //do your work here 
    } 
} 

- 添加任務,線程池是這樣的:

for(each task you need){ 
     Runnable worker = new WorkerTask(constructor params); 
     executor.execute(worker); 
    } 

最後,留下了兩個問題:

我該如何等待他們完成?

如何從線程返回值?

事實是,這兩個問題都有很多方法可以解決問題,但我認爲在這種情況下,您可以做一些簡單的事情。我推薦一個全局靜態變量,它將具有全局範圍並且能夠被所有線程訪問。在這裏要小心,不要編輯與其他線程相同的值,因此請使用類似於ConcurrentHashMap的東西,並且當線程有其答案時,只需將線程ID及其答案添加到哈希映射中即可。例如:concurrentMap.add(threadId,value);

要等到所有的任務都做了,我通常做這樣的事情:

executor.shutdown(); //signal that you want to shutdown executor 
while(!executor.isTerminated()){ 
     Thread.sleep(10000); //wait ten seconds 
     System.out.println("Waiting 10 seconds"); 
} 
// now finally traverse your value map and output your answers 
+0

這個答案的唯一問題是你使用名字'WorkerThread'。這些不是線程。他們是*任務*。使用一個暗示它們是線程的名稱可能會使讀者感到困惑。 –

+0

@StephenC線程和任務之間有什麼區別? – hichris123

+0

是的,我可能應該解釋一下這個區別。這些是可運行的任務,線程池一旦決定「輪到他們運行」就會轉入線程。 生病編輯我的答案爲未來的讀者。 –

1

我喜歡與隊列線程輸入和輸出工作,只是看到在文檔的例子:http://download.java.net/jdk7/archive/b123/docs/api/java/util/concurrent/BlockingQueue.html

一般有2個。5個理由使用線程開始:

  1. 在多CPU系統
  2. 與IO處理時(顯示器,鼠標,鍵盤,插座,讀/寫文件等)
  3. 爲定時器

假設你是不是做IO和無需定時器,具有比系統的CPU更多的線程會減慢你dowwwwwwwwwwwn

+0

圖形用戶界面怎麼樣? ;) –

+0

GUI是IO,不是嗎? –

+0

你可以將它歸類爲那個。不是所有的guis都需要輸入,所以對於不理解爲什麼 –

3

在Java 8並行數學可以說是相當優雅。下面的代碼利用了「+」操作是加法的事實,因此可以按任意順序對值進行求和。

所以下面的代碼並行地創建一個數字序列並在單個線程中減少(加和)它們。

import java.math.BigInteger; 
import java.util.Optional; 
import java.util.concurrent.ThreadLocalRandom; 
import java.util.stream.IntStream; 

import static java.math.BigInteger.valueOf; 
import static java.util.concurrent.ThreadLocalRandom.current; 

public class Bignum { 
    public static void main(String[] args) { 
     Optional<BigInteger> sum = IntStream.range(0, 9000) 
      .parallel()  <-- this enables parallel execution 
      .mapToObj(value -> { 
       ThreadLocalRandom generator = current(); 

       int power = generator.nextInt(17) + 2; 
       int power1 = generator.nextInt(25) + 2; 
       int power2 = generator.nextInt(72) + 2; 

       BigInteger num = valueOf(generator.nextInt(7895) + 1); 
       BigInteger num1 = valueOf(generator.nextInt(1250) + 1); 
       BigInteger num2 = valueOf(generator.nextInt(9765) + 1); 

       BigInteger add = num.pow(power); 
       BigInteger add1 = num1.pow(power1); 
       BigInteger add2 = num2.pow(power2); 

       return add.add(add1).add(add2); 
      }) 
      .reduce(BigInteger::add); 

     System.out.println(sum.get()); 
    } 
} 
+1

添加確實是「可加性的」,但我認爲你的意思是可交換的:) –

+0

不願意被過多的肛門關於這個, 'reduce'需要關聯性,'+'是[Additive Group](http://en.wikipedia.org/wiki/Additive_group)中的二元操作。 :-) –