Во время работы над Android-приложением я наткнулся на что-то и хотел получить ваше мнение/помощь по этому вопросу.Android - Threads, Runnable и одновременный доступ к данным
Итак, в основном, я создаю несколько Runnable
s, которые запускаются в разных потоках. Все это Runnable
s вызывает метод ApplyContrast(...)
из класса SomeClass
, который запускает эти Runnable
s (более или менее одновременно). Этот метод ApplyContrast(...)
осуществляет доступ и изменяет int[]
этого же класса SomeClass
.
Так что мне было интересно, если это было/может быть проблемой? Я спрашиваю об этом, потому что я не получаю ожидаемый результат, когда я запускаю его более чем на один поток.
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:
Чтобы добавить немного больше информации о том, что (неправильно) результат:
Как я уже говорил выше, я не получаю ожидаемый результат всегда, когда Я обрабатываю данные в нескольких потоках. Когда обработка данных выполняется в нескольких потоках только данные, обработанные в первом потоке (который был запущен), являются правильными.
Вот некоторые фотографии, чтобы показать исходное изображение, ожидаемый результат и фактическое конечное изображение я получаю, когда многопоточность:
(Не против синих частей на верхнем и на нижней части картинки)
Ожидаемое результирующее изображение:
Фактическое результирующее изображение:
Вы можете видеть, что в последнем изображении мы имеем «2 части». Первая часть (вверху) - первая, обработанная 1-й нитью (это сделано правильно), а вторая (внизу) обрабатывается всеми оставшимися нитями (это не так).
Верно, что переменная 'len' неверна. Я проверял ее содержимое, и там нет ничего плохого. Я обновил сообщение. Пожалуйста, посмотрите, есть ли у вас время. – Moucheg