LINUX.ORG.RU

помогите разобраться с примером

 , ,


0

1

В книжке Beginning Android games есть кусок кода, про вынос отрисовки картинки в отдельный тред. Непонятно, за счёт чего в данном случае прерывается бесконечный цикл в методе pause().

По идее в отдельном треде работает только метод run()? Что происходит, когда из основного треда вызывается метод объекта запущенного в дополнительном треде, в каком треде он выполняется?

class FastRenderView extends SurfaceView implements Runnable {
    Thread renderThread = null;
    SurfaceHolder holder;
    volatile boolean running = false;

    public FastRenderView (Context context) {
        super(context);
        holder = getHolder();
    }

    public void resume () { // вызывается из onResume() в родительской Activity
        running = true;
        renderThread = new Thread(this);
        renderThread.start();
    }

    public void run () {
        while (running) {
            if (!holder.getSurface().isValid())
                continue;
            Canvas canvas = holder.lockCanvas();
            canvas.drawRGB(255,0,0);
            holder.unlockCanvasAndPost(canvas);
        }
    }

    public void pause () { // вызывается из onPause() в родительской Activity
        running = false;
        while (true) {
            try {
                renderThread.join();
            } catch (InterruptedException e) {
                //
            }
        }
    }
}

Непонятно, за счёт чего в данном случае прерывается бесконечный цикл в методе pause().

while (running)

ziemin ★★ ()
Ответ на: комментарий от ziemin

Не, как останавливается run как раз понятно.

А вот в pause как завершается while(true)? Или его каким-то образом вместе с run останавливает?

Lonli-Lokli ★★ ()
Ответ на: комментарий от Lonli-Lokli

Никак.

Этот метод не относится к Runnable. Это самоделка.

Суть в том, что Interrupted exception это единственное исключение, которое выбрасывает join. Во всяких эклипсах такой вызов без try подчёркивается. Если клацнуть не глядя по предупреждению ide обернёт вызов в try. Вот кто-то и клацнул.

while(true) это уже самостоятельное творчество, т.к. join без параметров блокирует поток и повторять вызов не нужно.

upd: кстати он неправильно называется. Логичнее было бы stop, так как поток вырубается.

ziemin ★★ ()
Последнее исправление: ziemin (всего исправлений: 1)
Ответ на: комментарий от ziemin

В книжке оно сопровождается таким описанием:

Метод FastRenderView.pause() выглядит немного странно. В его начале мы уста- навливаем флаг running равным false (это сигнал для метода FastRenderView.run() остановить обработку и закрыть поток). Следующие несколько строк — ожидание полного уничтожения потока, осуществляемое вызовом метода Thread.join() . Этот метод ждет уничтожения потока, но может также вызвать исключение InterruptedException до того, как поток на самом деле сгинет. Поскольку нам необ- ходимо быть абсолютно уверенными в уничтожении потока, прежде чем возвра- щаться из этого метода, мы выполняем Thread.join() в безусловном цикле до тех пор, пока операция не будет завершена успешно.

И тут создаётся впечатление, что либо происходит что-то неявное, но очевидное явистам, либо пример - говно.

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

Lonli-Lokli ★★ ()
Ответ на: комментарий от Lonli-Lokli

Видел я такой абсолютно уверенный код. Почему ты априори считаешь автора правым? Верь глазам своим. Метод будет завершён вместе с приложением. Поставь после его вызова отладочный вывод и посмотри, сработает ли он когда нибудь.

Кроме того interruptedexception выбрасывается, если ты вызовешь join у уже остановленного потока! Т.е. уже можно быть уверенным, что поток либо остановился либо останавливается.

Нормальяная работа данной конструкции на железке

Какая загрузка процессора при вызове этого метода?

Ну либо андроид ставит какие-то дополнительные ограничения на колбэки жизненного цикла Activity (что, в принципе, вариация первого пункта).

В программировании не принято скрытое поведение.

ziemin ★★ ()
Ответ на: комментарий от ziemin

Просто while(true) (в том числе с try-catch внутри) в рандомном месте приводит к тому, что проект перестаёт компилироваться, ругаясь на unreachable statement. А тут получается какой-то специальный случай, распознаваемый компилятором?

Lonli-Lokli ★★ ()
Ответ на: комментарий от Lonli-Lokli

unreacheable statement это код после while(true) {}. Добавь ниже отладочный вывод и компилятор заругается.

ziemin ★★ ()
Последнее исправление: ziemin (всего исправлений: 1)
Ответ на: комментарий от ziemin

Кроме того interruptedexception выбрасывается, если ты вызовешь join у уже остановленного потока!

в обычной джаве не так, хз что там в ведроиде но по самой логике когда это исключение выбрасывается - такого быть не может.

maloi ★★★★★ ()
Ответ на: комментарий от ziemin

Собственно, я криво проверял, оно действительно не работает.

Lonli-Lokli ★★ ()
Ответ на: комментарий от ziemin

в обычной яве вызов join у уже остановленного потока просто выходит сразу.

maloi ★★★★★ ()
Ответ на: комментарий от ziemin

бросить исключение или вести себя согласно документации - невелика разница?

maloi ★★★★★ ()
Ответ на: комментарий от ziemin

А еще задокументировано когда оно выбрасывается

maloi ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.