2016-05-23 2 views
1

Я довольно новичок в Java; (< = lol Я просто набрал точку с запятой вместо точки (после 2-х дней безостановочного кодирования). Оставляя ее там, чтобы все могли смеяться: D)Вещи, похоже, работают параллельно Java

Я не был уверен, что искал, поэтому название не очень полезно.

Best я могу описать, что вещи, кажется, идут параллельно. Я не знаю, как объяснить это, так что я покажу вам пример. у меня есть класс таймера, который ждет на протяжении каждой петли.

Если я запускаю следующий метод (не в классе таймера, а только один), он не дожидается завершения законченной части (Таймера), например, для цикла делать. Он одновременно вычисляет код ниже.

Как заставить программу ждать окончания таймера? Кроме того, почему он работает параллельно?

Я урезал большинство ненужных кодов, но, пожалуйста, спросите, нужен ли вам весь код.

t = Timer; 
public void turnend() { 
    if (leftover == 0) { 
     housenumber = 1; 
     Runnable r = new Runnable() { 
      @Override 
      public void run() { 
       //code1 
       if (housenumber == 8) { 
        t.stopTimer(); 
       } 
      } 
     }; 
     t = new Timer(r, 500, true); 
    } 
    //code 2 
} 
//code 1 and 2 runs at the same time 

EDIT: Таймер класса

import android.os.Handler; 

public class Timer { 
private Handler handler; 
private boolean paused; 

private int interval; 

private Runnable task = new Runnable() { 
    @Override 
    public void run() { 
     if (!paused) { 
      runnable.run(); 
      Timer.this.handler.postDelayed (this, interval); 
     } 
    } 
}; 

private Runnable runnable; 

public int getInterval() { 
    return interval; 
} 

public void setInterval(int interval) { 
    this.interval = interval; 
} 

public void startTimer() { 
    paused = false; 
    handler.postDelayed (task, interval); 
} 

public void stopTimer() { 
    paused = true; 
} 

public Timer (Runnable runnable, int interval, boolean started) { 
    handler = new Handler(); 
    this.runnable = runnable; 
    this.interval = interval; 
    if (started) 
     startTimer(); 
} 

}

+0

исполняемую объект, который работает на своем собственном потоке. Вы можете использовать обратный вызов, когда таймер заканчивается использованием runOnUiThread – Striker

+0

@Striker Right. Но я хочу ждать Runnable. Я только что прочитал о обратном вызове, и кажется, что он просто буквально перезванивает, когда Таймер заканчивается. Следовательно, он не ждет Таймера. Пожалуйста, поправьте меня, если я ошибаюсь. – Seung

+0

Зачем ждать? Вы можете выполнить код, который у вас есть в методе 'run' после« кода 2 ». Кроме того, что это за класс 'Timer'? Это/запускает ли он 'Thread' (для параллельного запуска кода)? Кажется, это не 'java.util.Timer' или' javax.swing.Timer', и я не знаю, какой из них встроен в android. – zapl

ответ

1

основной поток Android выглядит немного как

while (true) { 
    Runnable nextThingToDo = getNextTaskFromQueue(); 
    nextThingToDo.run(); 
} 

и Handler с используются поставить новую задачу в очередь. Весь код, который вы пишете в on???? методах, таких как Activity#onCreate, также является частью таких задач. Такие вещи, как обработка сенсорных событий &, также отображаются в этой очереди чертежные обновления экрана. Поэтому вы никогда не должны приостанавливать этот поток, единственный способ сделать что-то «позже» - это сделать его очередью позже (очередь не простая очередь в первом порядке, она поддерживает задержки и т. Д.)

, ваш Timer рассылает taskRunnable для запуска после установленной задержки. Поскольку код, который вызывает handler.postDelayed, обязательно уже находится внутри такого запуска, он должен быть выполнен до того, как очередь может принять и запустить task. Так что же происходит в раскатывают в то время как петля примерно

Runnable nextThingToDo = getNextTaskFromQueue(); 
nextThingToDo.run(); 
// inside above "run"... whatever code path leads to turnend() 
    if (leftover == 0) { 
     housenumber = 1; 
     Runnable r = construct();// it's only a reference to a `Runnable` object, nothing executes here 
     t = new Timer(r, 500, true); 
     // inside Timer 
      handler.postDelayed(task, 500); // task is now in the queue 
    } 
    //code 2 -- it actually runs now. 
// whatever else is in your code on the way out from "turnend()" 

// ... things happen, 500ms passes 

Runnable nextThingToDo = getNextTaskFromQueue(); // this is the `task` object 
nextThingToDo.run(); 
// inside this "run" 
    if (!paused) { 
     runnable.run(); // this is the `r` object 
     // inside task 
      { 
      // code1 -- running ~ 500ms after code2 
      if (housenumber == 8) { 
       t.stopTimer(); 
      } 
      } 

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

Например, перемещая код физически в том месте, где она принадлежит:

public void turnend() { 
    if (leftover == 0) { 
     housenumber = 1; 
     Runnable r = new Runnable() { 
      @Override 
      public void run() { 
       //code1 
       if (housenumber == 8) { 
        t.stopTimer(); 
       } 
       //code 2 
      } 
     }; 
     t = new Timer(r, 500, true); 
    } 
} 

Или обеспечивая дальнейший код со ссылкой на код, который вы хотите назвать, это то, что называется «обратного вызова ».В это простейшая форма:

public void turnend() { 
     final Runnable callback = new Runnable() { 
      @Override 
      public void run() { 
       //code 2 
      } 
     }; 

     if (leftover == 0) { 
      housenumber = 1; 
      Runnable r = new Runnable() { 
       @Override 
       public void run() { 
        //code1 
        if (housenumber == 8) { 
         t.stopTimer(); 
        } 
        callback.run(); 
       } 
      }; 
      t = new Timer(r, 500, true); 
     } 
    } 

Everytime вы хотите написать

public void things() { 
     // code 1 
     // delay of 500 
     // code 2 
    } 

Вместо делать примерно:

public void thingsPart1() { 
     // code1 

     handler.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       thingsPart2(); 
      } 
     }, 500); 
    } 

    public void thingsPart2() { 
     // code 2 
    } 
+0

Блестящий! Большое спасибо. :) – Seung

1

Если вы хотите, чтобы заблокировать текущую тему, вы должны использовать Thread.sleep (500) статический метод вместо таймера.

+0

Aha. Благодарю. Я не знал о «Thread». Я прочитаю об этом больше. Любые другие объяснения более чем приветствуются :) – Seung

+1

@Seung, однако, не используйте 'sleep' в основном потоке Android (https://developer.android.com/guide/components/processes-and-threads.html#Threads объясняет немного), это просто заморозит приложение на мгновение (включая все анимации, не реагируя на касания и т. д.). Вам нужно будет использовать что-то вроде http://stackoverflow.com/a/9166354/995891, чтобы иметь правильный эффект. – zapl

+0

Я только что видел ваши изменения, хотя я использовал Таймер из Java API (https://docs.oracle.com/javase/8/docs/api/java/util/Timer.html) – Toilal

Смежные вопросы