Форум программистов, компьютерный форум, киберфорум
Наши страницы

Программирование Android

Войти
Регистрация
Восстановить пароль
 
кверти
4 / 4 / 1
Регистрация: 22.09.2013
Сообщений: 166
Завершенные тесты: 2
#1

Непонятное поведение многопоточного приложения - Программирование Android

12.05.2016, 20:00. Просмотров 307. Ответов 8
Метки нет (Все метки)

Всем добрый день. Ввожу в курс дела: я пишу игру под android и мне потребовалась в игре небольшая система, которая будет рендерить пул объектов хранящийся в HashMap<Integer, Object>.
Эта мапа заполняется в отдельном потоке. Элементы в мапу добавляются с небольшим промежутком времени(чтобы потом рендерились не все объекты сразу)
Вот код метода run();
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
    public void run() {
        if(!shotdown) {
            for(int i = 0; i < sizeArray; i++) {
                try {
                    Thread.sleep(100);
                    dummies.put(position, new Dummy(BodyFactory.createDummy(world)));
                    position++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        shotdown = !shotdown;
    }
Код тривиален... каждые 100 мс добавляем в мапу объект, который в дальнейшем будет рендериться

Для дальнейшего понимания: Есть некоторый класс Level унаследованный от Thread, соответственно код выше относится к этому классу
Объект класса Level создается в классе отвечающем за игровой мир. Вот код этого класса
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
public class PlayState extends State {
    private float frameCount;
    private World world;
    private Box2DDebugRenderer debugRenderer;
    private OrthographicCamera camera;
    private Level level;
    private SpaceShip spaceShip;
 
    public PlayState(GameStateManager gsm) {
        super(gsm);
        frameCount = 0;
        Constans.WIDTH = Gdx.graphics.getWidth();
        Constans.HEIGHT = Gdx.graphics.getHeight();
 
        world = new World(Constans.GRAVITY, Constans.SLEEP);
        world.setContactListener(new ContactObject());
 
        camera = new OrthographicCamera(Constans.WIDTH / 2, Constans.HEIGHT / 2);
        camera.position.set(new Vector2(100.0f, 100.0f), 0);
 
        debugRenderer = new Box2DDebugRenderer();
 
        level = new Level(world);
        level.start();
        spaceShip = new SpaceShip(BodyFactory.createSpaceShip(world));
    }
 
    @Override
    protected void handleInput() throws InterruptedException {
        if(Gdx.input.getX() >= 0 && Gdx.input.getX() <= 40 && Gdx.input.getY() >= Constans.HEIGHT -45 && Gdx.input.getY() <= Constans.HEIGHT +30) {
            dispose();
            gsm.set(new MenuState(gsm));
        }
 
        if(spaceShip != null) {
            if (Constans.STYLE_CONTROL) {
                spaceShip.tapControl();
            } else {
                spaceShip.AccControl();
            }
        }
    }
 
    @Override
    public void update(float time) throws InterruptedException {
        camera.setToOrtho(false, Constans.WIDTH / 2, Constans.HEIGHT / 2);
        handleInput();
 
        if(spaceShip != null) {
            spaceShip.update(time);
        }
        for (Map.Entry entry : level.getDummies().entrySet()) {
            if(entry != null && entry.getValue() instanceof Dummy) {
                level.checkScreen(entry.getValue(), level.getPosition());
                Dummy dummy = (Dummy) entry.getValue();
                level.setPosition((Integer) entry.getKey());
                dummy.update(time);
            }
        }
    }
 
    @Override
    public void render(SpriteBatch batch) throws InterruptedException {
        world.step(1f, 2, 2);
        debugRenderer.render(world, camera.combined);
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        frameCount += Gdx.graphics.getDeltaTime();
        batch.draw(Constans.BG_PLAY_SCREEN.getKeyFrame(frameCount, true),0, 0);
 
        if(spaceShip != null) {
            batch.draw(spaceShip.getParameters().getTypeShip(), spaceShip.getPosition().x, spaceShip.getPosition().y);
        }
        for (Map.Entry entry : level.getDummies().entrySet()) {
            if(entry != null && entry.getValue() instanceof Dummy) {
                level.checkScreen(entry.getValue(), level.getPosition());
                Dummy dummy = (Dummy) entry.getValue();
                level.setPosition((Integer) entry.getKey());
                batch.draw(dummy.getParameters().getSkin(), dummy.getPosition().x, dummy.getPosition().y);
            }
        }
 
        batch.draw(Constans.SETTING_PLAY_SCREEN, 0, 0);
        batch.end();
    }
 
    @Override
    public void dispose() {
        if(spaceShip != null) {
            spaceShip.resetParameters();
        }
        if(level != null) {
            level.stop();
            level.dispose();
        }
    }
}
В методе update и render мы пробегаемся по всем объектам нашего пула и вызываем соответствующие методы для обновления и рендеринга каждого объекта.
На словах все вроде бы не сильно сложно. Но по итогам такого алгоритма возникает куча непонятных проблем.
1) Игра крашится, спустя некоторое количество отрисованых объектов
2) Методы update и render у объектов, которые отрисовываются отрабатывают не до конца.
А конкретно выглядит это так: объект отрисовался прошло 100мс(время указанное в методе run) и он исчезает. После отрисовывается другой объект. Почему так происходит? Ведь каждый элемент пула ссылается на разные объекты, а не на один и тот же.
В логах нет никаких вылетов ошибок и прочего. Приложение просто останавливается и все...
Буду благодарен за помощь.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.05.2016, 20:00
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Непонятное поведение многопоточного приложения (Программирование Android):

Непонятное поведение программы! - Программирование Android
есть счетчик, который выводит цифры в TextView (подобие секундомера) есть кнопка запуска, она же остановки счетчика. Кнопка...

Непонятное поведение ArrayList - Программирование Android
У меня есть код, который циклом достаёт данные из базы данных и помещает их в HashMap, а оттуда уже типа HashMap помещает в ArrayList....

Непонятное поведение при повороте экрана - Программирование Android
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listpick); ...

Непонятное отображение spinner - Программирование Android
Здравствуйте! &lt;TableRow android:id=&quot;@+id/tableRow3&quot; android:layout_width=&quot;match_parent&quot; ...

Непонятное поведение - C++
Всем привет! В книге &quot;Прата - Язык программирования C++. Лекции и управжения 2011&quot; нашёл вот такой пример: const free_throws &amp;clone(...

Непонятное поведение ОС - Windows 7
Здрасте! Купил новый комп, а он загружается через раз (чаще через несколько раз), выключается долго, и один раз не вышел из спячки. ...

8
Alexvp
111 / 75 / 8
Регистрация: 03.08.2014
Сообщений: 380
13.05.2016, 09:50 #2
Конечно, это ваше личное дело. Но зачем изобретать велосипед? Возьмите, например, движок LibGDX, где все эти процессы нижнего уровня хорошо реализованы и протестированы. И сосредоточьтесь на gameplay своей игры.
1
vxg
Модератор
3224 / 2027 / 231
Регистрация: 13.01.2012
Сообщений: 7,868
13.05.2016, 10:03 #3
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от кверти Посмотреть сообщение
Почему так происходит?
вы добавляете в мап объекты в потоке и перебираете этот же мап в другом потоке что бы отрисовать элементы - откуда уверенность в том что мап потокобезопасен и его не расторащит от одновременного перебора и добавления? где Semaphore на худой случай?
1
кверти
4 / 4 / 1
Регистрация: 22.09.2013
Сообщений: 166
Завершенные тесты: 2
13.05.2016, 12:47  [ТС] #4
Спасибо за ответ. А можно узнать какие классы в libGdx позволяют реализовать данный механизм? Дело в том, что я взял за основу этот фреймворк, но, видимо, плохо в нем еще ориентируюсь

Добавлено через 42 секунды
Спасибо, попробую
0
Pablito
2631 / 2113 / 656
Регистрация: 12.05.2014
Сообщений: 7,398
Завершенные тесты: 1
13.05.2016, 14:42 #5
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
http://developer.android.com/intl/ru...ntHashMap.html
https://habrahabr.ru/post/132884/
2
Alexvp
111 / 75 / 8
Регистрация: 03.08.2014
Сообщений: 380
13.05.2016, 20:20 #6
Цитата Сообщение от кверти Посмотреть сообщение
А можно узнать какие классы в libGdx позволяют реализовать данный механизм
В сети навалом неплохих уроков по этому движку.
Одно могу сказать, что большое число объектов рендить накладно.
0
vxg
Модератор
3224 / 2027 / 231
Регистрация: 13.01.2012
Сообщений: 7,868
14.05.2016, 00:42 #7
Цитата Сообщение от Alexvp Посмотреть сообщение
Одно могу сказать, что большое число объектов рендить накладно.
позвольте с вами в этом вопросе согласиться и довести мысль до логического завершения - минимальная нагрузка на процессор будет если не рендерить вообще ничего
0
Alexvp
111 / 75 / 8
Регистрация: 03.08.2014
Сообщений: 380
14.05.2016, 13:23 #8
Цитата Сообщение от vxg Посмотреть сообщение
минимальная нагрузка на процессор будет если не рендерить вообще ничего
Логично
Уменьшение числа объектов можно делать за счет их группировки, но это зависит от геймплея игры. Однажды мне пришлось часть объектов включать в фоновый рисунок, так как они должны были быть на экране, но не были активными. Таким образом, вместо полутора десятков объектов рендился только один.
0
vxg
Модератор
3224 / 2027 / 231
Регистрация: 13.01.2012
Сообщений: 7,868
14.05.2016, 17:24 #9
Alexvp, если он рендерился то без разницы сколько вы напихали единиц в группу а если это рисунок то и ежу понятно что нет нужды бить фон на 1000 элементов
0
14.05.2016, 17:24
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.05.2016, 17:24
Привет! Вот еще темы с ответами:

Непонятное поведение кнопки - HTML, CSS
Кнопка home смещается при нажатии, после чего занимает свою позицию до перезагрузки браузера, причем наблюдается такое в браузере chrome, в...

Непонятное поведение компилятора - C++ WinAPI
При запуске программы пишет build sucessful. При следующем запуске ничего не происходит: нету ни окна в области Build пусто, в процессах...

Непонятное поведение консоли - Cisco
Здравствуйте все. Просьба помочь. У меня проблема с Cisco 2600. IOS 12.4. Проблема в следующем: Cisco была сброшена на дефолтовый...

MD5 непонятное поведение - Delphi
Доброе утро, Помогите разобрать MD5. Есть формула : ss1 = md5(data + password) password - '123123123' data -...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru