Здравствуйте, уважаемые. Запускаю задачу. Теоретический сценарий: отрабатывает 1 поток, затем отрабатывают 3 потока, затем 1. В принципе все работает правильно. Вставил sout, чтоб посмотреть как 3 потока переплетаются, и О, чудо! они работают друг за дружкой, единственное изменение - это их порядок выполнения. | Код | public class MyRunnable implements Runnable { /** * Функция, которая вычисляет значение по аргументу * @see #result(double) */ protected Function f; /** * Владелец, монитор. */ protected Stage owner;
/** * * @param f - функция, от которой будет считаться результат * @param owner - хозяин, монитор */ public MyRunnable(Function f, Stage owner) { setFunction(f); setOwner(owner); }
/** * * @param function - функция, от которой будет считаться результат */ public MyRunnable(Function function) { this(function, null); }
/** * Установка владельца * @param s - хозяин, монитор */ public void setOwner(Stage s) { this.owner = s; }
/** * Установка функции * @param f - функция */ public void setFunction(Function f) { this.f = f; } public void run() { Date time1 = new Date(); double res = 0; for (int i = 0; i < 30000; i++) { res += result(i); if (Tester.DEBUG) { if (i % 3000 == 0) System.out.println(this + " current calculation result = " + res); Thread.currentThread().yield(); } } if (Tester.DEBUG) System.out.println(this + " calculation result: " + res); synchronized(owner.getStorage()) { owner.getStorage().sum += res; } synchronized(owner) { owner.readyThreads++; owner.notifyAll(); } Date time2 = new Date();
if (Tester.DEBUG) System.out.println(this + " process time: " + (time2.getTime() - time1.getTime())); }
/** * Вычисление фунции * @param x - аргумент функции * @return результат функции * @see #f */ public double result(double x) { return f.result(x); }
public String toString() { return f.toString(); } }
|
| Код | public class Stage { /** * Следующее звено в цепи вычислений. * @see Lab2.Stage */ private Stage next;
/** * набор потоков, выполняющих параллельную рабуоту. * @see Lab2.MyRunnable */
private MyRunnable[] threadGroup;
/** * Хранилище данных, является null, если звену не было переданно задание или результат был посчитан * @see Lab2.Storage */
protected Storage storage;
/** * Число потоков из группы threadGroup, выполнивших вычисления */ protected int readyThreads; /** * Приоритет всех потоков */ protected int priority = Thread.NORM_PRIORITY;
/** * Основной конструктор * @param next - следующее звено в цепи вычислений * @param threadGroup - набор потоков, реализующих текущее задание данного звена */ public Stage(Stage next, MyRunnable[] threadGroup) { this.next = next; this.threadGroup = threadGroup; }
/** * Устанавливает приоритет потоков * @param priority - приоритет потока */ public void setPriority(int priority) { this.priority = priority; if (next != null) next.setPriority(priority); }
/** * Проверка, готово ли звено принять новое задание * @return true - готово, false - не готово */ public boolean isReadyRead() { return storage == null; }
/** * Проверка, готово ли звено выдать результат * @return true - готово, false - не готово */ protected boolean isReadyOutput() { return readyThreads >= threadGroup.length; }
/** * Возвращает хранилище * @return Хранилище данных */ // TODO был синхом public Storage getStorage() { return storage; }
/** * Устанавливает хранилище * @param st - хранилище данных */ // TODO был синхом void start(Storage st) { storage = st; for (int i = 0; i < threadGroup.length; i++) { Thread t = new Thread(threadGroup[i]); t.setPriority(priority); t.start(); } }
/** * Проверка, есть ли у звена последующее продолжение * @return true - продолжение имеется false - отсутствует */ public boolean hasNext() { return (next != null); }
/** * Ожидает выполнение всех частей задачи, выдача следующего звена цепи вычислений с установленным хранилищем данных * @return следующее звено цепи вычислений */
public Stage getNext() { while (!isReadyOutput()) { try { synchronized(this) { wait(); } } catch (InterruptedException e) {} }
readyThreads = 0; if (next != null) {
while(!next.isReadyRead()) { synchronized(next) { try { next.wait(); } catch (InterruptedException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } } next.start(storage); } storage = null; synchronized(this) { notifyAll(); } return next; }
/** * Устанавливает группу потоков * @param threadGroup - группа потоков, вычисляющих подзадачи данного этапа */ public void setThreadGroup(MyRunnable[] threadGroup) { this.threadGroup = threadGroup; } }
|
| Код | public class Conveyer { /** * Входное звено вычислений */ protected Stage startStage;
/** * * @param stage - начальное состояниие вычислений * @see #startStage */
public Conveyer(Stage stage) { startStage = stage; }
/** * Основная функция, вычисляет глобальное задание * @return результат вычислений */ public double compute() { if (Tester.DEBUG) { System.out.println("----------------------------------"); System.out.println("Conveyer: computing sum"); } Storage storage = new Storage(); Stage cur = startStage; synchronized(cur) { while (!cur.isReadyRead()) { try { cur.wait(); } catch (InterruptedException e) {} } }
cur.start(storage); while (cur.hasNext()) { cur = cur.getNext(); }
synchronized(cur) { while (!cur.isReadyOutput()) { try { cur.wait(); } catch (InterruptedException e) {} } } double res = cur.getStorage().sum; cur.getNext(); if (Tester.DEBUG) System.out.println("Conveyer: computing result: " + res); return res; }
/** * Устанавливает приоритет начальному звену * @param priority - новый приоритет потока */ public void setPriority(int priority) { startStage.setPriority(priority); } }
|
| Код | public class Builder { /** * Генерация структуры задачи * @return входное звено решения задачи */ public static Stage build() {
Stage stage3 = new Stage(null, null); MyRunnable[] thGroup = new MyRunnable[]{new MyRunnable(new P5Function(), stage3)}; stage3.setThreadGroup(thGroup);
Stage stage2 = new Stage(stage3, null); thGroup = new MyRunnable[]{new MyRunnable(new P2Function(), stage2), new MyRunnable(new P1Function(), stage2), new MyRunnable(new P4Function(), stage2)}; stage2.setThreadGroup(thGroup);
Stage stage1 = new Stage(stage2, null); thGroup = new MyRunnable[]{new MyRunnable(new P3Function(), stage1)}; stage1.setThreadGroup(thGroup);
return stage1; } }
|
Conveyer c = new Conveyer(Builder.build()); c.compute(); Свой вопрос я разрешил с помошью FlasH, очень ему признателен +. Ну и в принципе, хотелось бы услышать замечания по ныне навороченному коду. Это сообщение отредактировал(а) Platon - 26.3.2007, 10:40
|