W
W
WTFAYD2017-08-18 23:43:35
Java
WTFAYD, 2017-08-18 23:43:35

How to wait for all tasks to complete in order to perform some action in another task?

Task: to design a model of a radiation counter. There are several sensors that read in parallel once per second, the radiation counter should show the average value of all sensors.
At the moment the code is:

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();
    }
}

Is it possible to wait for all threads (in my case two) to complete - that is, wait until they add a value in 1 measurement cycle, and then divide it by the number of sensors?
And in general, is the line of thought correct when building a model? Have not finished the topic of multithreading yet, there are many contradictions and doubts in my head.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
i_visseri, 2017-08-19
@WTFAYD

You can use ExecutorService from java.util.concurrent to perform measurement tasks. I tried to sketch.
I have each sensor to perform a measurement creates a measurement task:

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;
            }
        }
    }

In the RadioMeter class, I have a list of all sensors, in it I also create an ExecutorService with a pool for as many threads as I have sensors:
Then the getResult() method of RadioMeter receives a list of all measurement tasks from all sensors and gives them to the Executor 'y(the invokeAll() method waits until all tasks have been completed):
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;
    }

Well, in the aggregateResults () function, the average value is simply considered.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question