繁体   English   中英

Android-线程,可运行和并发数据访问

[英]Android - Threads, Runnable and concurrent data access

在使用Android应用程序时,我偶然发现了一些东西,并希望获得您对此主题的意见/帮助。

因此,基本上,我正在创建几个在不同线程中运行的Runnable 所有这些Runnable从运行这些RunnableSomeClass类调用方法ApplyContrast(...) (或多或少同时运行)。 ApplyContrast(...)方法访问和修改同一类SomeClassint[]

所以我想知道这是否会是一个问题? 我问这个问题是因为我在1个以上的线程上运行时没有得到预期的结果。

PS:即使可以同时访问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:

要添加更多有关(错误)结果是什么的信息:

就像我在上面说的那样,无论何时在多个线程中进行数据处理,都不会得到预期的结果。 当在多个线程中完成数据处理时, 只有第一个线程(已运行)中处理的数据是正确的。

以下是一些图片,它们显示了多线程处理时获得的原始图像,预期结果和实际生成的图像:

(不要介意图像顶部和底部的蓝色部分)

原始图片: 在此处输入图片说明

预期的结果图像: 在此处输入图片说明

实际产生的图像: 在此处输入图片说明

您可以看到在上一张图片中我们有“两部分”。 第一部分(在顶部)是由第一个线程处理的部分(正确完成),第二部分(在底部)由所有其余线程处理的部分(这是错误的)。

我认为还可以。

从多个线程访问数组pixels (可能别名为mPixels )。 那将使它不正确。

但是,您似乎正在分块访问数组,以便每个线程仅访问自己的块。 只要多个线程从不访问数组中的同一位置,代码就是正确的。

不过,我必须说,这令人困惑。 我会说变量len是错误的。 当然,并发正确性确实很难确定。 我相信它可以写得更清楚,而且由于容易出错,因此值得这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM