Управление потоками

 
0
 
Java
ava
Pawl | 20.02.2013, 13:17
Доброго времени суток!
Опять вопрос по управлению потоками. Теперь задался целью сделать пример управления одним потоком другими. Задача следующая: есть несколько потоков, меняющих значение переменной value класса CheesyCounter. Контролирующий поток (в моем случае поток, в котором выполняется метод main), периодически проверяет значение value, и, если оно достигло определенного предела (константа limit в методе main), завершает потоки, изменяющие value. Потоки, которые меняют value, собраны в массив. Код классов:

import java.util.concurrent.CyclicBarrier;

public class Main {
    public static void main(String ...args) {
        //предел вычислений переменной value класса CheesyCounter
        final int limit = 3000;
        //массив классов для вычисления value в разных потоках
        RunnerInc [] r = new RunnerInc[3];
        CheesyCounter counter = new CheesyCounter();
        CyclicBarrier barrier = new CyclicBarrier(r.length, Thread.currentThread());
        //инициализация потоков
        for (int i = 0; i < r.length; i++) {
            r[i] = new RunnerInc(counter, barrier);
        }

        //запуск потоков, пока value не достигнет предела
        while (counter.getValue() < limit) {
            for (RunnerInc runner : r) {
                runner.start();
            }
        }

        //если предел достигнут, печать value и количеств запусков каждого потока
        if (counter.getValue() >= limit) {
            System.out.println("value = " + counter.getValue());
            for (int i = 0; i < r.length; i++) {
                System.out.println("number of iterations of thread" + i + ": " + r[i].getCount());
            }
        }
    }
}

//класс, обрабатываемый в потоках
public class CheesyCounter {
    private volatile int value;

    public int getValue() {
        return value;
    }

    public synchronized void increment() {
        value++;
    }
}

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class RunnerInc implements Runnable {
    private CheesyCounter counter;
    //количество запусков потока
    private int count;
    private CyclicBarrier barrier;

    public RunnerInc(CheesyCounter counter, CyclicBarrier barrier) {
        this.counter = counter;
        this.barrier = barrier;

    }

    public void start() {
        new Thread(this).start();
    }

    @Override
    public void run() {
        count++;
        counter.increment();
        try {
            barrier.await();
        } catch (BrokenBarrierException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public int getCount() {
        return count;
    }
}
Что мне не нравится:
- в цикле while метода main на каждой итерации создается новый поток
- конечное значение value часто бывает больше заданного предела.
Понятно, что это велосипед, буду благодарен, если покажете, каким должен быть классный байк. smile 
Ответы (2)
ava
Pawl | 21.02.2013, 21:34 #
Вобщем, переделал примерно так, как хотел. Нашел статью, сделал аналоги приостановки/запуска, как там написано. Сделанное приводить не буду, т. к. выглядит оно достаточно монстровито, да и вообще, похоже, управление остановкой / запуском нескольких потоков из одного лучше рассматривать на других задачах. Тему пока закрывать не буду, может, кто поделится своим опытом в этой области.
ava
Pawl | 01.03.2013, 17:08 #
Вот, нашел задачу, более приближенную к реальности: создание нескольких секундомеров в разных потоках с возможностью их приостановки, остановки и сброса. Приведу и приложу код решения (проект в Idea), посмотрите, пожалуйста, может, посоветуете, что можно улучшить?
Код секундомера:

public class Stopwatch implements Runnable {
    private int id;
    private boolean pause;
    private volatile int time;
    private volatile boolean stop;

    public Stopwatch(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public int getTime() {
        return time;
    }

    public void setStop(boolean stop) {
        this.stop = stop;
    }

    public boolean getStop() {
        return stop;
    }

    public void start() {
        stop = false;
        pause = false;
        new Thread(this).start();
    }

    public void reset() {
        time = 0;
    }

    public synchronized void setPause(boolean pause) {
        this.pause = pause;
        if (!pause) {
            notify();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
                synchronized (this) {
                    if (pause) {
                        wait();
                    }
                    if (stop) {
                        break;
                    } else {
                        time++;
                        System.out.println(time);
                    }
                }
            } catch (InterruptedException e) {}
        }
    }
}

Код управляющего класса (управление с консоли):

import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {
    private static Map<Integer, Stopwatch> stopwatches = new HashMap<>();
    private static Stopwatch stopwatch;

    public static Stopwatch getStopwatch(Integer number) throws NullPointerException {
        if (stopwatches.get(number) == null) {
            throw new NullPointerException();
        }
        return stopwatches.get(number);
    }

    public static void main(String ...args) {
        System.out.println("ready");
        Scanner s = new Scanner(new InputStreamReader(System.in));
        while (true) {
            String[] watchers = s.nextLine().split(" ");
            String watcher = watchers[0];
            Integer number = (watchers.length < 2) ? 0 : Integer.valueOf(watchers[1]);
            try {
                switch (watcher) {
                    case "start":
                        try {
                            stopwatch = getStopwatch(number);
                            if (!stopwatch.getStop()) {
                                System.out.println("stopwatch " + stopwatch.getId() + " is yet started");
                                break;
                            }
                        } catch (NullPointerException e) {
                            stopwatch = new Stopwatch(number);
                            stopwatches.put(number, stopwatch);
                        }
                        stopwatch.start();
                        System.out.println("stopwatch " + stopwatch.getId() +  started");
                        break;
                    case "pause":
                        stopwatch = getStopwatch(number);
                        stopwatch.setPause(true);
                        System.out.println("stopwatch " + stopwatch.getId() + " paused");
                        break;
                    case "resume":
                        stopwatch = getStopwatch(number);
                        stopwatch.setPause(false);
                        System.out.println("stopwatch " + stopwatch.getId() + " resumed");
                        break;
                    case "getTime":
                        stopwatch = getStopwatch(number);
                        System.out.println("stopwatch " + stopwatch.getId() + ": " + stopwatch.getTime());
                        break;
                    case "stop":
                        stopwatch = getStopwatch(number);
                        stopwatch.setStop(true);
                        System.out.println("stopwatch " + stopwatch.getId() + " stopped. Time is: " +
                             stopwatch.getTime());
                        break;
                    case "reset":
                        stopwatch = getStopwatch(number);
                        stopwatch.reset();
                        System.out.println("stopwatch " + stopwatch.getId() + " time = 0");
                        break;
                    case "exit":
                        System.out.println("bye-bye!");
                        System.exit(0);
                    default:
                        System.out.println("invalid command");
                }
            } catch (NullPointerException z) {
                System.out.println("stopwatch don't exist yet");
            }
        }
    }
}
Зарегистрируйтесь или войдите, чтобы написать.
Фирма дня
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Участники
ava  Pawl
advanced
Отправить