2012-06-05 114 views
1

同步我採取的是計算Julia集的程序。它將使用多個線程,具體取決於可用的處理器數量。每個線程計算一條線,但只有當該線不被另一個線程計算時。這部分工作得很好。多線程安全在Java

但有時,當我測試它與更大的圖像(更多的線來計算,例如而不是getHeight() = 1200,我把它設置爲3000,有一些行被跳過)。我想讓它更安全,這樣不會有兩行計算,也不會跳過任何行。這裏是run()方法的代碼:我希望它這樣的工作

public void run() { 
    while (counter < getHeight()-1) { 
     synchronized(this) { 
      if (counter >= getHeight() -1) { //so that the last line will not be calculated >2 times. 
       return; 
      } 
      counter++; 
      image.setRGB(0, counter, getWidth(), 1, renderLine(counter), 0, 0); 
     } 
    } 
    } 

:如果所計算的當前行,線程便進入到下一行..不,它感到困惑,使線得到跳過..

我想這其實:

public void run() { 
    while (counter < getHeight()-1 && !working) { 
     synchronized(this) { 
      working = true; 
      if (counter >= getHeight() -1) { //so that the last line will not be calculated >2 times. 
       return; 
      } 
      counter++; 
      image.setRGB(0, counter, getWidth(), 1, renderLine(counter), 0, 0); 
      working = false; 
     } 
    } 
    } 

,但是,我不知道這是否會阻止訪問到另一個線程當某個線程已經工作,它將改變值「counter」,這意味着行可以跳過!

我需要一個布爾變量來通知線程實際工作的一條線嗎?有什麼建議?

+0

的方法run u可以有一個數組表示已經獲得的線的數量。但如果線數增加,肯定會使應用程序變慢。 – Asif

回答

5

你幾乎可以肯定做得太多自己的線程管理。使用ExecutorService可以在多個線程之間分配工作而不會有重複。

ExecutorService service = Executors.newFixedThreadPool(
    Runtime.getRuntime().availableProcessors()); 
for (int row = minRow; row <= maxRow; row++) { 
    service.submit(new FillThisRowRunnable(row)); 
} 
+0

我不能。它是一門功課,我們不應該用別的除了「同步」和「簡單」的方法和修飾:-),我已經處理器=調用Runtime.getRuntime()availableProcessors())。作爲我班的對象變量。我只是通過計算圖像的線條來處理更多的安全問題。正如我所說,它現在工作很好,但如果有人有任何建議,它會更安全,這將是非常有益的..謝謝! – ZelelB

+0

如果是家庭作業,應該使用[作業]標籤進行標記。 –

+1

ooopss!對不起Louis!現在完成! – ZelelB

1

你真的需要爲所有線程的共享對象。該對象將告訴其他線程處理哪一行。

我不能肯定的告訴你現在有什麼,但似乎每個​​是在你失去所有相互排斥的不同實例。請記住,當同步發生在共享對象上時,同步僅適用於多個線程,否則每個線程將在線程本地對象上同步,其中沒有任何內容可以實現。

下面是一個例子

public class SharedLineCounter{ 
    private final int maxNumberOfLines; 
    private int currentLineNumber =0; 
    public SharedLineCounter(int maxNumberOfLines){ 
     this.maxNumberOfLines = maxNumberOfLines; 
    } 
    public synchronized int getNextLine(){ 
     if(++currentLineNumber > maxNumberOfLines) 
     return -1; //end case 
     return currentLineNumber ; 
    } 
} 

public class WorkerThread extends Thread{ 
    private final SharedLineCounter counter; 
    public WorkerThread(SharedLineCounter counter){ 
     this.counter = counter; 
    } 
    public void run(){ 
     int next = -1; 
     while((next = counter.getNextLine()) >= 0){ 
     image.setRGB(0, next , getWidth(), 1, renderLine(next), 0, 0); 
     } 
    } 
    } 
} 

這裏每個線程將共享此線程安全線計數器,以便每個線程應該總是讓一個獨特的和連續的行號。

編輯回答你的問題:

可以使線程匿名通過共享的全局實例

public static void main(String args[]){ 
    final SharedCounter counter = new SharedCounter(); 

    Thread worker1 = new Thread(new Runnable(){ 
     public void run(){ 
      counter.getNextLine(); //etc 
     } 
    }); 
    Thread worker2 = new Thread(new Runnable(){ 
     public void run(){ 
      counter.getNextLine(); //etc 
     } 
    }); 

} 

一個警告,以解決基於您的評論。您應該通過new Runnable並創建一個匿名可運行的,它的壞習慣子類和覆蓋Thread

+0

感謝您的回答! 好的,教授給了我們同一班,但只使用一個處理器。所以我們可以比較我們的結果,如果它是禁食的,例如,如果我有4個處理器,使用多線程,它應該快4倍。雖然我的同步程序正在做某些事,因爲如果你的速度比他的班級快4倍(只使用一個沒有線程的處理器),當我告訴我時,我評論了我的同步塊,它仍然運行得更快4倍! O_o 所以是的,它沒有做任何事情,但是它怎麼會比他的班級跑4倍? – ZelelB

+0

對不起ZelelB我遇到了麻煩。哪個班級的共享計數器或沒有共享計數器的哪個班級速度快4倍? –

+0

我發佈的一個..但沒有「同步」其工作4倍快,圖像是好的! (沒有線路跳過) – ZelelB