[英]Android - Threads, Runnable and concurrent data access
在使用Android应用程序时,我偶然发现了一些东西,并希望获得您对此主题的意见/帮助。
因此,基本上,我正在创建几个在不同线程中运行的Runnable
。 所有这些Runnable
从运行这些Runnable
的SomeClass
类调用方法ApplyContrast(...)
(或多或少同时运行)。 此ApplyContrast(...)
方法访问和修改同一类SomeClass
的int[]
。
所以我想知道这是否会是一个问题? 我问这个问题是因为我在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.