Проблема со сном в Thread

При нажатии кнопки я вызываю следующую функцию.

private void badButtonHandler() {
    Camera.Parameters params = mCamera.getParameters();
    params.setColorEffect(Camera.Parameters.EFFECT_NEGATIVE);
    mCamera.setParameters(params);
    if(thread != null){
        thread = null;
    }
    thread = new Thread()
    {
        @Override
        public void run() {
            try {
                while(true) {
                    sleep(5000);
                    Camera.Parameters params = mCamera.getParameters();
                    params.setColorEffect(Camera.Parameters.EFFECT_NONE);
                    mCamera.setParameters(params);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    thread.start();
}

Эта функция предназначена для изменения цветового эффекта камеры через 5 секунд после нажатия кнопки. При первом нажатии соответствующей кнопки она ведет себя так, как ожидалось. Но дополнительные вызовы этой функции ведут себя не так, как ожидалось. То есть во второй раз ждет 2 секунды, после чего уменьшается до меньших значений с каждым кликом.


person Ahmed Nawaz    schedule 26.03.2013    source источник
comment
используйте флаг для управления потоком, потому что поток работает непрерывно после того, как вы нажимаете кнопку в первый раз   -  person ρяσѕρєя K    schedule 26.03.2013
comment
В Android я думаю, что вместо использования Thread лучше использовать Handler с методом postDelayed developer.android.com/reference/android/os/, длинный)   -  person nidhi_adiga    schedule 26.03.2013
comment
могу ли я остановиться после первого пробежки?? и снова бег..   -  person Ahmed Nawaz    schedule 26.03.2013
comment
Если вы хотите выполнить только один раз, зачем вам поток? Вы можете сделать то же самое в методе слушателя.   -  person Sudhanshu Umalkar    schedule 26.03.2013
comment
есть ли необходимость в while (true) - бесконечный цикл   -  person Code2Interface    schedule 26.03.2013
comment
@Sudhanshu Как именно вы ожидаете создать 5-секундную задержку, даже не касаясь нити?   -  person b1nary.atr0phy    schedule 26.03.2013
comment
Удален цикл while, теперь он работает нормально. спасибо @panky1986   -  person Ahmed Nawaz    schedule 26.03.2013
comment
Просто используйте sleep() для создания 5-секундной задержки.   -  person Sudhanshu Umalkar    schedule 26.03.2013
comment
@Судханшу Что? Во-первых, sleep() — это функция потока. Во-вторых, sleep() нельзя надежно использовать в качестве таймера (как уже объяснялось в этой ветке).   -  person b1nary.atr0phy    schedule 26.03.2013


Ответы (2)


Вы не должны не полагаться на sleep() как на точный таймер. Он не проснется автоматически в назначенное время и не станет текущим активным потоком из-за того простого факта, что все потоки находятся во власти планировщика потоков. Что, несомненно, будет варьироваться от ОС к ОС на основе данной JVM.

Я всегда полагался на пользовательские функции таймера для таких сценариев. Так, например:

myTimer(System.nanoTime());

public static void myTimer(long startTime) {
    while (startTime + 5000000000 > System.nanoTime()) { //Wait for 5 seconds
        try {
            Thread.sleep(50); //Sleep at ~50 millisecond intervals
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Вам не нужно будет создавать совершенно новый поток, как вы сделали в своем примере, поскольку Thread.sleep() переведет текущий поток в спящий режим. Кроме того, использование цикла while(true) — это просто плохая практика программирования.

Использование nanoTime() предпочтительнее, так как это самый точный системный таймер, доступный в Java.

Дополнительную информацию о ненадежности функции sleep() см. в этой документации.

person b1nary.atr0phy    schedule 26.03.2013
comment
Сон в Android можно упростить с помощью SystemClock.sleep(long). , который не выбрасывает InterruptedException - person Justin Muller; 26.03.2013
comment
@JustinMuller Я бы никогда не отказался от возможности прервать поток, если бы у меня не было для этого явной причины. Особенно, когда я хочу контролировать, что происходит, когда конечный пользователь нажимает кнопку спящего режима на своем устройстве за n секунд до истечения таймера. - person b1nary.atr0phy; 26.03.2013

попробуй это

Thread timer = new Thread(new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                //Your desired work
            }
        }
    });
    timer.start();
person Atif Farrukh    schedule 26.03.2013
comment
Добавление предложения finally не учитывает тот факт, что sleep() НИКОГДА не следует использовать в качестве таймера. - person b1nary.atr0phy; 26.03.2013