многопоточность с возможностью приостановки / продолжения вычислений - PullRequest
0 голосов
/ 14 декабря 2018

Я пишу Java-программу, которая позволяет мне получить геометрический центр случайно сгенерированных двумерных точек.Я хочу, чтобы расчеты производились по произвольному числу потоковЯ хочу приостановить / продолжить расчеты в любое время.К сожалению, мой код не работает, кажется, что run() никогда не выполняется.Вот что я получил:

public void run() {
    while (!Thread.currentThread().isInterrupted()) {

        try {
            System.out.println("running... " + Thread.currentThread().getName());

            PointInterface p = pg.getPoint(); // getting random point(x,y)
            pointCount++;
            int[] pos = p.getPositions(); // getting (x,y)
            System.out.println(pos[0] + ", " + pos[1] + " k");
            sumxy[0] += pos[0];
            sumxy[1] += pos[1];
            geometricCenter[0] = (double) sumxy[0] / pointCount;
            geometricCenter[1] = (double) sumxy[1] / pointCount;

            Thread.sleep(1000);
        } catch (InterruptedException e) {
            System.out.println("exception caught in run()");
            return;
        }
    }
}

Установка количества потоков:

public void setNumberOfThreads(int threads) {

    threadsList.clear();

    for (int i = 0; i < threads; i++) {
        threadsList.add(new Thread());
    }
}

Запуск расчетов:

public void start() {

    try {
        for (Thread t : threadsList) {
            t.start();
        }
    } catch (Exception e) {
        System.out.println("start() exception caught");

    }
}

Приостановка расчетов:

public void suspendCalculations() {

    try {
            Thread.sleep(1200);
    } catch (InterruptedException e) {
        System.out.println("SuspendCalculations() exception caught");
    }
}

Возобновление расчетов: я точно не знаю, что мне здесь делать.Должен ли я создать новый набор потоков, как это?

public void continueCalculations() {

    int x = threadsList.size();
    threadsList.clear();

    for (int i = 0; i < x; i++) {
        threadsList.add(new Thread());
        threadsList.get(i).start();
    }
}

Как мне запустить мою программу:

public static void main(String[] args) {

    ParallelCalculations pc = new ParallelCalculations(); // My main class object where run() and all the methods above are declared
    PointGenerator g = new PointGenerator(); // class that allows me to generate points
    PointInterface a = g.getPoint(); // getting random point

    pc.setNumberOfThreads(3);
    pc.setPointGenerator(g);
    pc.start();
    pc.suspendCalculations();
    System.out.println(pc.getGeometricCenter()[0] + ", " + pc.getGeometricCenter()[1]);

    pc.continueCalculations();
    pc.suspendCalculations();
    System.out.println(pc.getGeometricCenter()[0] + ", " + pc.getGeometricCenter()[1]);
}

При необходимости: Точка:

class Point {

    public static final int MAX_POSITION = 16;
    private int[] positions = new int[2];

    Point(int _x, int _y) {
        this.positions[0] = _x;
        this.positions[1] = _y;
    }

    public int[] getPositions() {
        return positions;
    }
}

Генератор точек:

class PointGenerator {

    private int x = (int) (Math.random() * (Point.MAX_POSITION + 1));
    private int y = (int) (Math.random() * (Point.MAX_POSITION + 1));

    public PointInterface getPoint() { //  Can be called by many Threads at the same time.

        return new Point(x, y);
    }
}

1 Ответ

0 голосов
/ 14 декабря 2018

Ваш run() должен быть выполнен и должен делать свое дело.

Хотя в этом коде есть гораздо большая причина для случайного поведения: все потоки записывают в sumxy, geometricCenter и pointCount в то же время без синхронизирующих блокировок, вызывающих более или менее случайное поведение.По крайней мере, вам нужно реализовать какую-то синхронизацию, чтобы предотвратить одновременную запись.

Возможно, запустите здесь (учебник по Java synchonized от Oracle), если у вас нет подсказки.

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

А теперь общеепроблемы:

A) Ваш suspendCalculations() ничего не делает (для 1200 мс будет точным).Чтобы нарушить вычисление, вам нужно прервать все рабочие потоки, так как они прерываются при прерывании.Для этого позвоните threadsList.get(i).Interrupt().

B) Если вы хотите иметь возможность изменять количество потоков, пока оно приостановлено, это способ.Если в этом нет необходимости, было бы эффективнее создать постоянную

 public static final Object LOCK = new Object();

, сделать все потоки LOCK.wait() для этого объекта, поэтому их возобновление - просто вызов LOCK.notifyAll().

C) Вместо использования вашей собственной реализации Point вы можете использовать java.awt.Point.

D) Возвращение координат точки просто в массиве очень плохо для читабельности вашего кода, java.awt.Pointимеет функции getX() и getY().

...