2016-08-27 6 views
0

Androidアプリで作業しているうちに、私は何かを見つけたが、その件に関するあなたの意見や助けを得たかった。Android - スレッド、ランナブル、同時データアクセス

基本的に、私は別のスレッドで動作するいくつかのRunnableを作成しています。これらすべてRunnableRunnableを実行するクラスSomeClassからApplyContrast(...)というメソッドを呼び出します(多少なりとも同時に)。 このApplyContrast(...)メソッドは、同じクラスのint[]にアクセスして変更します。SomeClass

私はこれが問題であるかどうか疑問に思っていましたか? 2つ以上のスレッドでこれを実行すると、期待した結果が得られないため、これを求めています。

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); 
     } 
    } 
} 

UPDATE#1:

は(間違った)結果が何であるかについて、もう少し情報を追加するには:私は上記に述べたように

、私はいつでも期待される結果を得ることはありません私はいくつかのスレッドでデータ処理を行います。 データ処理が複数のスレッドで行われた場合最初のスレッドで処理されたデータ(実行されたデータ)は正しいです。ここで

は、マルチスレッド時に私が取得元の画像、期待された結果と実際の結果の画像を表示するためにいくつかの写真です:

(一番上と画像の下部にある青色の部分を気にしないでください)

オリジナル画像: enter image description here

予想される結果の画像: enter image description here

実際の結果の画像: enter image description here

あなたは最後の画像では、我々は「2部」を持っていることがわかります。 1番目の部分(上端)は、1番目のスレッドで処理されたもの(これは正しく行われます)と残りの2番目のスレッドで処理されたもの(これは間違っています)です。

答えて

0

大丈夫だと思います。

アレイpixels(たぶん別名mPixels)は複数のスレッドからアクセスされます。それは間違っているでしょう。

しかし、各スレッドが独自のチャンクにのみアクセスできるように、アレイへのアクセスをチャンクしているように見えます。複数のスレッドが配列の同じ場所に決してアクセスしない限り、コードは正しいです。

しかし、私はそれが激しく混乱していると言わなければならない。私は変数lenが誤って命名されていると思います。確かに、並行性の正確さは本当に決定するのが難しいです。私はそれがより明確に書かれていると信じています。そして、誤りが起こりやすいもので、そうする価値があるでしょう。

+0

'len'変数の名前が間違っているのは事実です。私はそれが内容であることを確認して、何も間違っていません。 私の投稿を更新しました。時間があれば見てください。 – Moucheg

関連する問題