Как заставить эту программу отображать правильное значение в конце ее в Java? - PullRequest
0 голосов
/ 11 апреля 2020

У меня проблема с получением правильного значения в конце функции. Я не могу понять, как заставить основной поток ожидать выполнения до завершения sh, поэтому я могу отобразить правильное значение.

Каждая задача вычисляет произведение значений по индексу i в массивах. Я установил переменную product как volatile и синхронизировал функцию вычисления продукта, чтобы убедиться, что только один поток получает к нему доступ и изменяет его. Но я не могу организовать потоки, чтобы дождаться, пока исполнитель завершит sh, а затем покажет ответ.

 public class NewBetterDot {
static double[] vectorOne;
static double[] vectorTwo;
private static volatile double product;;

public NewBetterDot(double[] vectorOne, double[] vectorTwo, double product) {
    super();
    this.vectorOne = vectorOne;
    this.vectorTwo = vectorTwo;
    this.product = product;

}

public static synchronized double smallDot(int i) {

    double multi = vectorOne[i] * vectorTwo[i];
    return multi;
}

static class Task implements Runnable {
    int i;

    @Override
    public void run() {

        // System.out.println("Before operation: " + product);

        product = product + NewBetterDot.smallDot(i);

        System.out.println(Thread.currentThread().getName() + " Product is equal to: " + product);

    }

    public Task(int i) {
        super();
        this.i = i;
    }

}

static class PrintTask implements Runnable {
    @Override
    public void run() {
        System.out.println("Product equals to: " + product);
    }
}

public static void main(String[] args) throws NullPointerException {

    double sum = 0.0;
    NewBetterDot objectOne = new NewBetterDot(new double[] { 5.0, 4.0, 1.0 }, new double[] { 1.0, 2.0, 3.0 }, 0.0);

    int threshhold = vectorOne.length;

    ExecutorService executor = Executors.newFixedThreadPool(2);
    ;

    for (int i = 0; i < threshhold; i++) {

        NewBetterDot.Task task = new NewBetterDot.Task(i);

        executor.submit(task);

    }

    executor.shutdown();

    NewBetterDot.PrintTask pt = new NewBetterDot.PrintTask();
    pt.run();
}

}

Цитата

Ответы [ 2 ]

0 голосов
/ 11 апреля 2020

ExecutorService ожидает окончания всех потоков sh с помощью следующего метода

taskExecutor.shutdown();
try {
  taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
  ...
}

из Как ожидать окончания всех потоков sh, используя ExecutorService?

------- update ------

Ваши коды действительно беспорядочные, потому что вы используете поля и методы stati c для задачи потока, как мы обычно используем non-stati c объектов. Основываясь на вашем коде, я внес некоторые изменения, чтобы программа работала правильно. Ключевым моментом является то, что операция обновления продукта должна быть атомом c, а код выглядит следующим образом:

public static synchronized void addSmallDot(int i) {
    product += vectorOne[i] * vectorTwo[i];
    System.out.println(Thread.currentThread().getName() + " Product is equal to: " + product);
}

static class Task implements Runnable {
    int i;

    @Override
    public void run() {
        // System.out.println("Before operation: " + product);
        NewBetterDot.addSmallDot(i);
    }

    public Task(int i) {
        super();
        this.i = i;
    }

}

public static void main(String[] args) throws NullPointerException, InterruptedException {
    //...        
    executor.shutdown();
    executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    NewBetterDot.PrintTask pt = new NewBetterDot.PrintTask();
    pt.run();
}
0 голосов
/ 11 апреля 2020

Документация для shutdown() гласит:

Этот метод не ожидает завершения выполнения ранее представленных задач. Для этого используйте awaitTermination.

Этот код ожидает до 1 минуты для остановки вычислений:

executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
...