Лучший способ запустить код в течение определенного периода времени - PullRequest
8 голосов
/ 10 февраля 2011

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

Текущий код;

// Calculate the new lines to draw 
            Timer timer3 = new Timer();
            timer3.schedule(new TimerTask(){
                public void run(){
                    ArrayList<String> Coords = new ArrayList<String>();
                    int x = Float.valueOf(lastFour[0]).intValue();
                    int y = Float.valueOf(lastFour[1]).intValue();
                    int x1 = Float.valueOf(lastFour[2]).intValue();
                    int y1 = Float.valueOf(lastFour[3]).intValue();
                    //Could be the wrong way round (x1,y1,x,y)?
                    Coords = CoordFiller.coordFillCalc(x, y, x1, y1);
                    String newCoOrds = "";
                    for (int j = 0; j < Coords.size(); j++)
                    {
                        newCoOrds += Coords.get(j) + " ";
                    }
                    newCoOrds.trim();
                    ClientStorage.storeAmmendedMotion(newCoOrds);

                }

            }
            ,time);

Ответы [ 4 ]

16 голосов
/ 10 февраля 2011

Если вы используете Java5 или новее, рассмотрите ScheduledThreadPoolExecutor и Future.В первом случае вы можете запланировать выполнение задач после определенной задержки или через определенные интервалы, таким образом, он принимает на себя роль Timer, просто более надежно.

Средство Timer управляет выполнением отложенных («запустить эту задачу через 100 мс») и периодических («запускать эту задачу каждые 10 мс») задач.Однако у Timer есть некоторые недостатки, и ScheduledThreadPoolExecutor следует рассматривать как его замену.[...]

A Timer создает только один поток для выполнения задач таймера.Если задача таймера выполняется слишком долго, точность синхронизации других TimerTask s может пострадать.Если повторяющаяся TimerTask запланирована на выполнение каждые 10 мс, а другая TimerTask занимает 40 мс для запуска, повторяющаяся задача либо (в зависимости от того, была ли она запланирована с фиксированной скоростью или с фиксированной задержкой) вызывается четыре раза в быстрой последовательности последлительное задание завершает или «пропускает» четыре вызова полностью.Пулы запланированных потоков устраняют это ограничение, позволяя вам предоставлять несколько потоков для выполнения отложенных и периодических задач.

Другая проблема с Timer заключается в том, что он ведет себя плохо, если TimerTask выдает непроверенное исключение.Поток Timer не перехватывает исключение, поэтому непроверенное исключение, выброшенное из TimerTask, завершает поток таймера.Timer также не воскрешает поток в этой ситуации;вместо этого он ошибочно полагает, что все Timer было отменено.В этом случае TimerTask, которые уже запланированы, но еще не выполнены, никогда не запускаются, и новые задачи не могут быть запланированы.

С Параллелизм Java на практике , раздел 6.2.5.

И Future с могут быть ограничены для запуска не более в течение указанного времени (выбрасывая TimeoutException, если не удалось завершить время).

Обновление

Если вам не нравится вышеуказанное, вы можете настроить задачу на собственное время выполнения, как показано ниже:

int totalTime = 50000; // in nanoseconds
long startTime = System.getNanoTime();
boolean toFinish = false;

while (!toFinish) 
{
    System.out.println("Task!");
    ...
    toFinish = (System.getNanoTime() - startTime >= totalTime);
}
3 голосов
/ 10 февраля 2011

[...] В настоящее время я использую TimerTask, чтобы код мог выполняться в течение заданного промежутка времени [...]

Задача таймера никогда не остановит текущую задачу. Фактически, единственная цель - перезапускать задачу снова и снова.

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

0 голосов
/ 10 февраля 2011

Следует также отметить, что обычно вам нужно создать только один таймер (). Из фрагмента кода я бы предположил, что вы создаете несколько объектов Timer ().

Время в методе расписания - это время выполнения, а не продолжительность.

Подумайте о том, чтобы установить время начала до цикла for и сделать разрыв в цикле for, если вы превысили предел времени.

long startedAt = System.currentTimeMillis();
long finishedCorrectly = true;
for (int j = 0; j < Coords.size(); j++) {
  newCoOrds += Coords.get(j) + " ";
  if ((System.currentTimeMillis() - startedAt) > MAX_TIME_TO_RUN) {
    finishedCorrectly = false;
    break;
  }
}
0 голосов
/ 10 февраля 2011

Если при остановке вы имеете в виду, что программа должна завершиться, решение состоит в том, чтобы создать поток для вашей обработки и пометить его как демон, запустить его и в основном потоке в течение необходимого времени, а затем просто вернуться из * 1001. * метод.

Поцарапайте, что если вы остановитесь, вы просто остановите обработку.

...