#java #multithreading #executorservice
#java #многопоточность #executorservice
Вопрос:
Я создаю программу для вычисления значений двух массивов на этапах моделирования (они инициализируются с самого начала, я не ставил это здесь). Я хотел бы сделать это с помощью потоков и ExecutorService. Я разделил массивы на блоки и хочу, чтобы значения этих блоков вычислялись потоками, один блок = один поток. Эти два массива — X и Y — принимают значения друг от друга (как вы можете видеть в run()), я хочу, чтобы сначала вычислялся X, а затем Y, поэтому я создал два отдельных runnables:
public static class CountX implements Runnable {
private int start;
private int end;
private CountDownLatch cdl;
public CountX(int s, int e, CountDownLatch c) {
this.start = s;
this.end = e;
this.cdl = c;
}
public void run() {
for (int i = start 1; i < end - 1; i ) {
x[i] = x[i] - (y[i-1] - 2 * y[i] y[i 1]) y[i];
}
cdl.countDown();
}
}
И то же самое для округа. Я хотел бы предоставить ему информацию о том, где находится начальное и конечное значение для каждого блока.
Вот, вкратце, как выглядит мой майн, и это моя главная проблема:
int NN = 400; //length of X and Y
int threads = 8;
int block_size = (int) NN/threads;
final ExecutorService executor_X = Executors.newFixedThreadPool(threads);
final ExecutorService executor_Y = Executors.newFixedThreadPool(threads);
CountDownLatch cdl = new CountDownLatch(threads);
CountX[] runnables_X = new CountX[threads];
CountY[] runnables_Y = new CountY[threads];
for (int r = 0; r < threads; r ) {
runnables_X[r] = new CountX((r*block_size), ((r 1)*block_size), cdl);
}
for (int r = 0; r < threads; r ) {
runnables_Y[r] = new CountY((r*block_size), ((r 1)*block_size), cdl);
}
int sim_steps = 4000;
for(int m = 0; m < sim_steps; m ) {
for (int e = 0; e < threads; e ) {
executor_X.execute(runnables_X[e]);
}
for (int e = 0; e < threads; e ) {
executor_Y.execute(runnables_Y[e]);
}
}
executor_X.shutdown();
executor_Y.shutdown();
Я получаю неправильные значения массивов X и Y из этой программы, потому что я также делал это без потоков.
Необходим ли здесь CountDownLatch? Должен ли я выполнять цикл for runnables_X[r] = new CountX((r*block_size), ((r 1)*block_size), cdl);
в каждом цикле m (sim_step)? Или, может быть, мне следует использовать ExecutorService по-другому? Я перепробовал много вариантов, но результаты по-прежнему неверны.
Заранее благодарю вас!
Ответ №1:
Ваш подход — это тот, который я, вероятно, не принял бы для этой задачи.
Вы можете работать со ссылками и исполняемыми файлами, но в вашем случае вызываемый объект может быть лучшим выбором. С помощью вызываемого объекта вы просто предоставляете ему массив и позволяете ему вычислять частичное значение, если это возможно, и ожидаете Futures
. Для меня не совсем ясно, что вы на самом деле хотите вычислить, поэтому я беру слепое предположение здесь.
Вам не нужно CountDownLatch
ни одного, ни двух ExecutorServices
— достаточно одного EXS.
Если вы действительно хотите использовать a Runnable
для этого, вам следует реализовать какую-то синхронизацию, либо с параллельным списком, атомарными переменными, volatile
либо с блокировкой.
Комментарии:
1. Я вычисляю значения X и Y, которые находятся в run() исполняемых файлов
2. Это немного шире. Вы только поделились своим вычислением x, которое каким-то образом связано со значениями y . Когда x зависит от y, который должен быть вычислен первым, вы должны сначала выполнить вычисление y, дождаться результатов, а затем вычислить x. Кроме того, массивы не являются потокобезопасными.
3. y также зависит от x так же, как x зависит от y . В любом случае спасибо! Я постараюсь работать с Callable здесь.