2016-08-27 13 views
0

在Android應用程序上工作時,我偶然發現了一些東西,希望得到您對此主題的意見/幫助。Android - 線程,可運行和併發數據訪問

所以,基本上,我創建了幾個在不同線程中運行的Runnable。所有這些Runnable s都調用SomeClass類的方法ApplyContrast(...),該類運行這些Runnable(或多或少地同時)。 這個ApplyContrast(...)方法訪問和修改同一類SomeClassint[]

所以我想知道這是/可能是一個問題? 我在問這個,因爲當我在多於1個線程上運行時,我沒有得到預期的結果。

P.S:即使有到int[]併發訪問線程不訪問數組的相同部分(或不應該這樣做:P)

任何幫助是值得歡迎的。如果您需要更多信息,請詢問。

public class SomeClass extends SomeOtherClass { 

    // The number of threads that will be used to do the data processing 
    private static int mNumberOfThreadsToCreate = 10; 

    private int mPixelArrayLength; 

    private int mRunningThreadCount; 

    public SomeClass(AnotherClass callback, int[] pixels, int length) { 
     super(callback, pixels); 

     mPixelArrayLength = length; 
     mRunningThreadCount = mNumberOfThreadsToCreate; 
    } 

    public void run() { 
     new Thread(new Runnable() { 
      public void run() {  
       final int lenByChunk = mPixelArrayLength/mNumberOfThreadsToCreate; 
       for (int i = 0; i < mNumberOfThreadsToCreate; ++i) { 
        int len = lenByChunk; 
        if (i == (mNumberOfThreadsToCreate - 1)) 
         len += (mPixelArrayLength - mNumberOfThreadsToCreate * lenByChunk); 
        applyToChunk(mPixels, i * lenByChunk, len, 128); 
       } 
      } 
     }).start(); 
    } 

    private void applyToChunk(final int[] pixels, final int offset, final int len, final int contrastLevel) { 
     new Thread(new Runnable() { 
      public void run() { 
       applyContrast(pixels, offset, len, contrastLevel);  
       --mRunningThreadCount;  
       onFinish(); 
      } 
     }).start(); 
    } 

    //set value in range 0 - 255 
    private int keepInRange(int colorValue) { 
     if (colorValue < 0) 
      colorValue = 0; 
     else if (colorValue > 255) 
      colorValue = 255; 

     return colorValue; 
    } 

    /** 
    * contrastLevel should be in <-128, 128> range 
    */ 
    private void applyContrast(int[] pixels, int offset, int pixelsLen, int contrastLevel) { 
     double correctionFactor = 259.047619047619; 
     double factor = (correctionFactor * (contrastLevel + 255))/(255 * (correctionFactor - contrastLevel)); 

     for(int i = offset; i < pixelsLen; ++i) { 

      int red = keepInRange((int)(factor * (Color.red(pixels[i]) - 128) + 128)); 
      int green = keepInRange((int)(factor * (Color.green(pixels[i]) - 128) + 128)); 
      int blue = keepInRange((int)(factor * (Color.blue(pixels[i]) - 128) + 128)); 
      int alpha = Color.alpha(pixels[i]); 
      pixels[i] = Color.argb(alpha, blue, green, red);//invert sequence here. 
     } 
    } 

    private void onFinish() { 
     // Shouldn't be < 0 or there is a really serious problem ... 
     if (mRunningThreadCount <= 0 && super.mCallback != null) { 
      super.mCallback.onFinish(super.mPixels); 
     } 
    } 
} 

更新#1:

要增加有關(錯誤的)結果就是更多的信息:

正如我前面所說,我沒有得到預期的結果,只要我在幾個線程中進行數據處理。 當數據處理在多個線程中完成時只有在第一個線程(已運行)中處理的數據是正確的。

這裏有一些畫面,展示原始圖像,預期的結果和實際產生的圖像多線程時,我得到:

(不介意頂部和圖像底部的藍色部分)

原始圖像: enter image description here

預期得到的圖像: enter image description here

實際產生的圖像: enter image description here

你可以看到,我們有「2份」最後的形象。第一部分(頂部)是由第一個線程處理的(這是正確完成的)和第二部分(在底部)由所有其餘線程處理(這是錯誤的)。

回答

0

我認爲沒關係。

數組pixels(可能別名爲mPixels)是從多個線程訪問的。這會使它不正確。

雖然看起來您正在分塊訪問數組,以便每個線程僅訪問其自己的塊。只要多個線程永遠不訪問數組中的同一個點,代碼就是正確的。

但是,我得說,它是非常混亂。我會說變量len是錯誤的。當然,併發性的正確性很難確定。我相信它可以寫得更清楚,而且,如果出現如此容易出錯的情況,那麼這樣做是非常值得的。

+0

確實len'變量是錯誤的。我檢查過它的內容,並沒有錯。 我已更新我的帖子。請看看你是否有時間。 – Moucheg