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

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

15
задан Hooked 6 March 2015 в 04:44
поделиться

5 ответов

Необходимо смотреть на эти классы: FutureTask, Вызываемый , Исполнители

Вот пример:

public class TimeoutExample {
    public static Object myMethod() {
        // does your thing and taking a long time to execute
        return someResult;
    }

    public static void main(final String[] args) {
        Callable<Object> callable = new Callable<Object>() {
            public Object call() throws Exception {
                return myMethod();
            }
        };
        ExecutorService executorService = Executors.newCachedThreadPool();

        Future<Object> task = executorService.submit(callable);
        try {
            // ok, wait for 30 seconds max
            Object result = task.get(30, TimeUnit.SECONDS);
            System.out.println("Finished with result: " + result);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (TimeoutException e) {
            System.out.println("timeout...");
        } catch (InterruptedException e) {
            System.out.println("interrupted");
        }
    }
}
11
ответ дан 1 December 2019 в 02:10
поделиться

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

Затем когда Вы хотите прерваться, просто необходимо вызвать прерывание на соответствующий поток.

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

8
ответ дан 1 December 2019 в 02:10
поделиться

Я принимаю использование нескольких потоков в следующих утверждениях.

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

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

7
ответ дан 1 December 2019 в 02:10
поделиться

Действительно, Вы не можете... Единственный способ сделать это состоит в том, чтобы или использовать thread.stop, договориться о 'совместном' методе (например, иногда проверять на Thread.isInterrupted или называть метод, который бросает InterruptedException, например, Thread.sleep ()), или так или иначе вызовите метод в другой JVM полностью.

Для определенных видов тестов, называя остановку () хорошо, но она, вероятно, повредит состояние Вашего набора тестов, таким образом, необходимо будет повторно запустить JVM после каждого вызова для остановки (), если Вы хотите избежать эффектов взаимодействия.

Для хорошего описания того, как реализовать совместный подход, проверьте FAQ Sun на методы Потока устаревшие .

Для примера этого подхода в реальной жизни, Задание RCP Eclipse API объект 'IProgressMonitor' позволяет некоторому сервису управления сигнализировать о подпроцессах (с помощью метода 'отмены'), что они должны остановиться. Конечно, это полагается на методы для фактической проверки isCancelled метода регулярно, который им часто не удается сделать.

гибридный подход А мог бы быть должен спросить поток приятно с прерыванием, затем настоять несколько секунд спустя с остановкой. Снова, Вы не должны использовать остановку в производственном коде, но могло бы быть хорошо в этом случае, особенно при выходе из JVM вскоре после.

Для тестирования этого подхода я записал простой ремень безопасности, который берет выполнимое и пытается выполнить его. Не стесняйтесь комментировать/редактировать.

public void testStop(Runnable r) {
    Thread t = new Thread(r);
    t.start();
    try {
        t.join(2000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }

    if (!t.isAlive()) {
        System.err.println("Finished on time.");
        return;
    }

    try {
        t.interrupt();
        t.join(2000);
        if (!t.isAlive()) {
            System.err.println("cooperative stop");
            return;
        }
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    System.err.println("non-cooperative stop");
    StackTraceElement[] trace = Thread.getAllStackTraces().get(t);
    if (null != trace) {
        Throwable temp = new Throwable();
        temp.setStackTrace(trace);
        temp.printStackTrace();
    }
    t.stop();
    System.err.println("stopped non-cooperative thread");
}

Для тестирования его я записал два конкурирующих бесконечных цикла, один кооператив и тот, который никогда не проверяет прерванный бит его потока.

public void cooperative() {
    try {
        for (;;) {
            Thread.sleep(500);
        }
    } catch (InterruptedException e) {
        System.err.println("cooperative() interrupted");
    } finally {
        System.err.println("cooperative() finally");
    }
}

public void noncooperative() {
    try {
        for (;;) {
            Thread.yield();
        }
    } finally {
        System.err.println("noncooperative() finally");
    }
}

Наконец, я записал тесты (JUnit 4) для осуществления их:

@Test
public void testStopCooperative() {
    testStop(new Runnable() {
        @Override
        public void run() {
            cooperative();
        }
    });
}

@Test
public void testStopNoncooperative() {
    testStop(new Runnable() {
        @Override
        public void run() {
            noncooperative();
        }
    });
}

я никогда не использовал Thread.stop () прежде, таким образом, я не знал о его операции. Это работает путем броска объекта ThreadDeath от того, везде, куда целевой поток в настоящее время работает. Это расширяет Ошибку. Так, в то время как это не всегда работает чисто, это будет обычно оставлять простые программы с довольно разумным состоянием программы. Например, любого наконец блоки называют. Если бы Вы хотели быть настоящим придурком, то Вы могли выгода ThreadDeath (или Ошибка), и продолжать бежать, так или иначе!

, Если ничто иное, это действительно заставляет меня пожелать большего количества кода, следовал за подходом IProgressMonitor - добавляющий другой параметр к методам, которые могли бы требовать времени, и поощрение конструктора метода иногда опросить объект Монитора видеть, хочет ли пользователь, чтобы система сдалась. Я попытаюсь следовать за этим шаблоном в будущем, особенно методы, которые могли бы быть интерактивными. Конечно, Вы не обязательно знаете заранее, какие методы будут использоваться этот путь, но для именно это Профилировщики, я предполагаю.

Что касается 'запускают другую JVM полностью' метод, который возьмет больше работы. Я не знаю, записал ли кто-либо загрузчик класса делегирования, или если бы Вы включены в JVM, но это требовалось бы для этого подхода.

3
ответ дан 1 December 2019 в 02:10
поделиться

Никто не ответил на это непосредственно, таким образом, вот самая близкая вещь, которую я могу дать Вам в небольшом объеме кода psuedo:

переносят метод в выполнимое/вызываемое. Сам метод оказывается перед необходимостью проверять на прерванное состояние, если Вы хотите, чтобы это остановилось (например, если этот метод является циклом в проверке цикла на Thread.currentThread () .isInterrupted и если так, остановитесь, цикл (не проверяйте каждое повторение, хотя, или Вы просто замедлите материал. в методе обертывания используйте thread.join (тайм-аут) для ожидания времени, Вы хотите позволить выполненному методу. или, в цикле там, называйте соединение неоднократно с меньшим тайм-аутом, если необходимо сделать другие вещи при ожидании. если метод не заканчивается после присоединения, используйте вышеупомянутые рекомендации для прерывания быстрого/чистого.

так код мудрый, старый код:

void myMethod()
{
    methodTakingAllTheTime();
}

новый код:

void myMethod()
{
    Thread t = new Thread(new Runnable()
        {
            public void run()
            {
                 methodTakingAllTheTime(); // modify the internals of this method to check for interruption
            }
        });
    t.join(5000); // 5 seconds
    t.interrupt();
}

, но снова, чтобы это работало хорошо, необходимо будет все еще изменить methodTakingAllTheTime, или тот поток только продолжит бежать, Вы назвали прерывание.

1
ответ дан 1 December 2019 в 02:10
поделиться