• ,

level28.lesson10.home01

Самое логичное решение, результат которого соответсвует выводу не проходит. Где я ошибся?


private static void start(List<Character> characters) throws InterruptedException {
        final Phaser phaser = new Phaser(1 + characters.size()); // 1 - чтоб зарегистрировать себя
        phaser.arriveAndDeregister();
        for (final Character character : characters) {
            final String member = character.toString();
            System.out.println(member + " присоединился к игре");
            new Thread() {
                @Override
                public void run() {
                    System.out.println(member + " готовится играть");
                    phaser.arriveAndAwaitAdvance();
                    if (!isEveryoneReady) {
                        isEveryoneReady = true;
                        System.out.println("Игра началась!");
                    }
                    character.run();
                }
            }.start();
        }
    }

43 комментария

valter
еще актуально
valter
До сих пор актуально
bfg
m.habrahabr.ru/post/117185/ последний пример ну просто 1 в 1.
Первая ссылка в гугле.
silh
Немного недопонимаю разницу этих решений для данной задачи. В случае, если писать как автор темы — мы убираем лишнего участника еще перед «забегом». В итоге кол-во тех, кто должен прибыть к старту известно уже точно заранее. Они прибывают по очереди и ожидают последнего. Как только пребывает последний — барьер открывается и они «бегут» дальше.
В примере же, приведенном по ссылке, пребывают все, кроме одного, участники «забега» и тут выясняется, что этого последнего и не будет, его вычеркивают из списков ожидания и барьер открывается…
Может я что-то упускаю и есть какая-то сильно большая разница в данном примере?
San_Lex
Задача с шуткой юмора. В условии сказано:
Не должно быть закоментированного кода
Убираем // 1 — чтоб зарегистрировать себя и задача не проходит пока не вернешь обратно.
have some fun :)
sokolov
Сейчас стало еще интереснее — условие приходит без этого комментария, но без этого комментария задача не принимается!
Naissur
Ничего подобного. Может, конечно, было исправление, но у меня задача принялась без всяких комментариев.
kolust
isEveryoneReady по идее должна быть volatile. без нее у меня «Игра началась» выводится два раза!Hubert прошу поправить.
noroving
да согласен не красиво получается)
vladimirsencov
volatile не поможет, так как не гарантирует атомарность операций, тем более здесь идет две операции подряд сравнение и присваивание.
Проблему удалось победить при помощи AtomicBoolean.getAndSet().
levka
  • levka
  • 0
  • Комментарий отредактирован 2014-12-15 14:13:33 пользователем levka
Я вот только не понял почему не надо использовать phase.register()? Как в примере по ссылке… Кто-нибудь может разъяснить?
vladimirsencov
потому что в конструкторе уже стоит нужное число для счетчика
PolyMorph
Вывод как в output.txt. Почему не проходит?
private static void start(List<Character> characters) throws InterruptedException {
        final Phaser phaser = new Phaser(1 + characters.size()); // 1 - чтоб зарегистрировать себя

        for (final Character character : characters) {
            final String member = character.toString();
            System.out.println(member + " присоединился к игре");
            new Thread() {
                @Override
                public void run() {
                    System.out.println(member + " готовится играть");
					phaser.arriveAndAwaitAdvance();
                    if (!isEveryoneReady) {
                        isEveryoneReady = true;
                        System.out.println("Игра началась!");
                    }
                    character.run();
					phaser.arriveAndDeregister();
                }
            }.start();
        }
		phaser.arriveAndDeregister();
    }
vladimirsencov
package com.javarush.test.level28.lesson10.home01;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Phaser;

/* Plants vs Zombies
1. Почитайте про java.util.concurrent.Phaser
2. Расставь методы в нужных местах
-arriveAndDeregister() - начинает запускать методы run у тасок
-arriveAndAwaitAdvance() - ждет, когда все трэды будут созданы

Пример вывода см. в output.txt
Логика:
Сначала все персонажи присоединяются к игре.
После того, как все персонажи присоединятся к игре и готовы играть, выводится фраза "Игра началась!".
После этого персонажи вступают в игру, после чего умирают.
Не должно быть закоментированного кода
*/
public class Solution {
    public static void main(String[] args) throws InterruptedException {
        List<Character> characters = new ArrayList<>();
        characters.add(new Plant());
        characters.add(new Plant());
        characters.add(new Zombie());
        characters.add(new Zombie());
        characters.add(new Zombie());
        start(characters);
    }

    private static boolean isEveryoneReady = false;

    private static void start(List<Character> characters) throws InterruptedException {
        final Phaser phaser = new Phaser(1 + characters.size()); // 1 - чтоб зарегистрировать себя

        for (final Character character : characters) {
            final String member = character.toString();
            System.out.println(member + " присоединился к игре");
            new Thread() {
                @Override
                public void run() {
                    System.out.println(member + " готовится играть");
                    phaser.arriveAndAwaitAdvance();
                    if (!isEveryoneReady) {
                        isEveryoneReady = true;
                        System.out.println("Игра началась!");
                    }
                    phaser.arriveAndAwaitAdvance();
                    character.run();
                }
            }.start();
        }
        phaser.arriveAndDeregister();
    }
}

Проблема не сильно отличается вывод такой:
Plant #1 присоединился к игре
Plant #2 присоединился к игре
Zombie #1 присоединился к игре
Plant #2 готовится играть
Zombie #2 присоединился к игре
Zombie #3 присоединился к игре
Zombie #2 готовится играть
Zombie #1 готовится играть
Plant #1 готовится играть
Zombie #3 готовится играть
Игра началась!
Zombie #1 вступил в игру
Zombie #2 вступил в игру
Plant #2 вступил в игру
Zombie #3 вступил в игру
Plant #1 вступил в игру
Zombie #1 умер
Zombie #3 умер
Plant #1 умер
Zombie #2 умер
Plant #2 умер
vladimirsencov
Но иногда проскакивает двойной или тройной вывод «Игра началась»
bo4ek
phaser.arriveAndAwaitAdvance() — ставится в run, чтобы он ждал пока ему не скажут действовать. Так как он в цикле, то команду начинать надо вызвать, когда цикл закончится
vladimirsencov
Но задачу все равно не принимает хоть Хуберту пиши
bo4ek
у меня все принялось. Я тебя тебя ошибка, что ты дважды возвращаешь значение фазора

тут есть нечто похожее на эту задачу
examples.javacodegeeks.com/core-java/util/concurrent/phaser/java-util-concurrent-phaser-example/
svorobei
спасибо. прочитав комментарий, наконец-то разобрался в теме)
Mostric
у меня не проходило просто потому что исходник с сервака не загружал коммент "// 1 — чтоб зарегистрировать себя". Когда только зашёл сюда понял, какая должна быть 34-я строка. Вот такая
final Phaser phaser = new Phaser(1 + characters.size()); // 1 - чтоб зарегистрировать себя

Блин, тупизм. Писали же, что задачи пофиксили.
Nazgul
Вот так спасибо)
evilfrag
/facepalm

так-то спасибо огромное)
sokolov
Спасибо. При том что я уже пробовал этот вариант, но скопировал комментарий с одним слэшом, а не с двумя)))
Aerys
лол реально, добавил комент и прошло
Jinray
Огромное спасибо, нашел же.
Чем ближе к 40му, тем тупее валидатор, и больше ошибок. Сначало веселило, теперь раздражает((
quazrckk
._.
BigVOVA
Прошел без // 1 — чтоб зарегистрировать себя
Vasago
Может, кому-то поможет. В загружаемом коде в строке
final Phaser phaser = new Phaser(1 + characters.size());

без объяснения причин добавлена лишняя группа. У меня принялось, когда убрал «1 + ». Иначе фейзер просто вечно ждал группу, которой не существует.
Grytcyna_Oleg
Блин тупизм, задача не принималась лишь из за того что File Encoding стоял в UTF-8 и выводилась абра кодабра
Plant #1 присоединился к игре
Plant #2 присоединился к игре
поменял на windows-1251 и все из за этого задача не принималась, давайте делать тогда все на English, чтоб не было проблем с локализацией!
ab_random
  • ab_random
  • 0
  • Комментарий отредактирован 2016-03-27 22:49:17 пользователем ab_random
Нормально задача работает. Не нужно никаких лишних комментариев добавлять, читайте внимательно условие.

Подсказка: потоки надо в определенное время запустить, вот и всё. С регистрации они снимутся сами, «посмертно».
PS… и пофиг, что «Игра началась!» иногда выводится повторно=)
Bakh
  • Bakh
  • +2
  • Комментарий отредактирован 2016-06-14 13:24:58 пользователем Bakh
вуд
RBlik
  • RBlik
  • 0
  • Комментарий отредактирован 2016-06-22 22:00:19 пользователем RBlik
чтобы задача принялась и чтобы аутпут совпадал — 2 абсолютно разных челенжа).

ПЫ.СЫ. чтобы всего 1 раз писало «Игра началась» приходилось добавить arriveAndAwaitAdvance и в блок if
и в (вдобавок созданный) else ))) тогда независимо от результата нить ждала. НО ЭТО НЕ КАСАЕТСЯ УСЛОВИЯ ЗАДАЧИ. :D это так… для тех, кто задается вопросом. хотя вопрос остается. видимо моментально все нити берут ее значение чтобы изменить
PodKrepkimCh
Как в данном задании Paser понимает, что нити являются его участниками?
Вызов метода arriveAndAwaitAdvance(), он присоединяет нить, в которой вызван, к пасеру в состоянии прибыла на барьер?
Paser понимет, что нити являются его участниками за счет методов arriveAndAwaitAdvance и arrive? Без их вызова в данной задаче он будет пустой?
RBlik
а он и не знает… просто заметь, перед созданием нитей мы создали фазер размером с количество нитей + нить main. на месте вызова arriveAndAwaitAdvance нить отмечается (при этом кол во в списке фазера если к примеру 10 нитей при создании указано, он даст сигнал только когда все 10 отметятся то есть все время идет обратный счетчик на каждом таком брейкпоинте) когда все отметились они вместе опять продолжают бежать… в конце мы делаем деригистр чтобы убрать нить main из списка. ведь из за нее будет постоянно при обратном отсчете недосчет одной. а вообще я читал обьяснение пыдыыыщь
RBlik
там у этой штуковины дофига прикольных методов. можно например отметиться и погнать дальше.
PodKrepkimCh
А при чем тут нить мейн? ведь она не отмечается я в пасере с помощью метода arriveAndAwaitAdvance.
В предыдущем комментарии я не прав, вызов метода arriveAndDeregister по сути уменьшает количество участников на 1, а не сообщает о общей разрегистрации. К примеру, если бы пасер был на 7 участников, к барьеру пришло 5, то для их прохода через барьер надо дважды вызвать arriveAndDeregister.
Спасибо еще раз) погряз я в этих нитях)
Prokrasti
фазер же, блин
PodKrepkimCh
спасибо
Как я понял нить с помощью метода arriveAndAwaitAdvance отмечается о прибытии на барьер и ждет прихода всех остальных участников. Таким образом, за недостатком одной нити, все они встают на барьер и ждут. И ждали бы вечно одного недостающего участника, если бы не метод arriveAndDeregister который сообщает о всеобщей разрегистрации, и все нити продолжают свой бег. Правильно?
RBlik
да ну все было бы норм, если б в задании не регистрировали на одну больше нить чтобы потом мы сами догадывались дерегистрацию делать… видимо, чтоб показать, как можно шаманить в этом фазере…
есть штука такая CountDownLatch в пакете java.util.concurrent. и делает она похожие вещи… (из названия видно)… но походу Фазер поразностороннее будет.
Medved81m
Пробовал кучу разных вариантов. Прошло только после того, как разблокировал барьер основной нитью. Видимо именно для этого ее в конструктор и добавляли. Несколько выводов «Игра началась» не препятствует сдаче задачи.
lichMax
Примерно также как у автора, но валидатор не принимает решение. Уже не знаю, что делать.
lichMax
Хе, всяко-разно попробовал и прочитал уже все темы по этой задаче на хелпе. Потом тупо скопировал какое-то решение, найденное в интернете (на гитхабе), и всё прошло. (Хотя расставлял нужные методы также, как в этом найденном решение; фигня какая-то; заметил уже такое, что вроде бы написано также, а у меня не проходит, а у кого-то проходит, а когда тупо скопируешь этот код и вставишь в файл, так сразу проходит, и валидатор решение принимает)
RelaxeR
Тоже просидел долго с этой задачей, вроде что к чему понял, вывод получал, но не принимало — пишет оба метода не на своих местах. Прочитал ваш комментарии, нашел решение — такое же как у меня. Скопировал метод старт — приняло метод arriveAndDeregister(), типа теперь на своем месте, хотя реально ничего не изменилось вообще. А второй метод также не принимало. Скопировал весь класс целиком — приняло задачу. Чудеса просто.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.