@WTFAYD

Как дождаться выполнения всех задач, чтобы выполнить какое то действие в другой задаче?

Задание: спроектировать модель радиационного счетчика. Есть несколько сенсоров, которые параллельно дают показание раз в секунду, радиационный счетчик должен показывать среднее значение всех сенсоров.

На данный момент вышел такой код:
import java.util.*;
import java.util.concurrent.*;

class RadiationMeter {
    private int value = 0;
    private int sensorCounter = 0; // the amount of plugged sensors
    private List<Sensor> sensors = new LinkedList<>(); // plugged sensors list
    private Thread t = new Thread(new Measuring());

    private synchronized void addToValue(int sensorValue) {
        value += sensorValue;
    }

    private class Measuring implements Runnable { // sensors values processing and writing a result
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                // waiting until all threads add their values to sensorCounter
                // and then dividing by sensorCounter
            }
        }
    }

    public void start() {  // starting the meter and the sensors
        for(Sensor s : sensors)
            s.turnOn();
        t.start();
    }

    public class Sensor {
        private int value;
        private String name;
        private final int min; // range of a measurment error
        private final int max;
        private Thread t;

        public Sensor(String name, int min, int max) {
            value = 0;
            this.min = min;
            this.max = max;
            this.name = name;
            t = new Thread(new Measuring(),name);

            if (!sensors.contains(this))
                sensors.add(this);
        }

        public void turnOn() {
            RadiationMeter.this.sensorCounter++;
            t.start();
        }

        public void turnOff() {
            RadiationMeter.this.sensorCounter--;
            t.interrupt();
        }

        private class Measuring implements Runnable { // measuring by sensor
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    addToValue(ThreadLocalRandom.current().nextInt(min, max + 1)); // adding to the meter value
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        return;
                    }
                }
            }
        }

    }
}

public class Program {
    public static void main(String[] args) throws Exception {
        RadiationMeter rm = new RadiationMeter();
        RadiationMeter.Sensor s1 = rm.new Sensor("s1",10,20);
        RadiationMeter.Sensor s2 = rm.new Sensor("s2",10,20);
        rm.start();
    }
}


Есть ли возможность дождаться выполнения всех потоков (в моем случае два) - то есть подождать, пока они прибавят значение за 1 цикл измерения, и затем разделить его на количество сенсоров?
И в общем, правильный ли ход мысли при построении модели? Еще не закончил тему многопоточности, есть много противоречий и сомнения в голове.
  • Вопрос задан
  • 171 просмотр
Решения вопроса 1
@i_visseri
Вы можете использовать ExecutorService из java.util.concurrent для выполнения задач измерений. Попробовал набросать.
У меня каждый сенсор для выполнения измерения создает задачу измерения:
public static class Sensor {

        private String name;
        private int delta = 1;

        public Sensor(String name) {
            this.name = name;
        }

        public SensorMeasuring getSensorMeasuringTask() {
            return new SensorMeasuring();
        }

        private class SensorMeasuring implements Callable<Integer> {

            @Override
            public Integer call() throws Exception {
                System.out.println("Запущен сенсор: " + name + " ");
                Random random = new Random();
                int result = random.nextInt(10) - delta;
                System.out.print("Результат: " + result);
                return result;
            }
        }
    }


В классе RadioMeter у меня есть список всех сенсоров, в нем я создаю также ExecutorService с пулом на столько потоков, сколько у меня сенсоров:

executorService = Executors.newFixedThreadPool(5);

Потом метод getResult() у RadioMeter у меня получает список всех задач на выполнение измерения от всех сенсоров и отдает их Executor'у(метод invokeAll() ждет, пока все задачи не будут выполнены):

public long getResult(){
        List<Callable<Integer>> measuringTasks = new ArrayList<>();
        for(Sensor sensor : sensors) {
            measuringTasks.add(sensor.getSensorMeasuringTask());
        }
        List<Future<Integer>> results;
        try {
            results = executorService.invokeAll(measuringTasks);
            return aggregateResults(results);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 0L;
    }


Ну и в функции aggregateResults() просто считается среднее значение.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы