Запустить поток с заданным временем выполнения
Мой основной процесс вызывает метод внешней библиотеки. Этот метод иногда зависает. Я не могу починить внешнюю библиотеку, потому что за это отвечает другая компания.
Я хочу использовать поток для библиотечных вызовов с определенным таймером выполнения. Когда вызов метода занимает длительное время, поток с Runnable, в который помещается вызов метода, должен остановиться, а основной процесс должен идти вперед.
- Main Thread wait
- Выполнить поток
- начало Начало таймер Тема
- Когда поток таймера закончен, убейте Execute Thread
- Выполнить остановку потока Main
- резюме темы
У кого-нибудь есть код, для которого эта логика, шаблон дизайна, который я могу использовать, или интернет-страница, на которой я могу прочитать некоторую информацию?
Спасибо
3 ответа
Посмотрите на java.lang.concurrent
пакет в Java 5 и позже, в частности CompletionService
интерфейс и классы, которые его реализуют.
Этот интерфейс включает вызовы, которые позволяют отправить задачу и либо дождаться ее завершения, либо продолжить после истечения времени ожидания.
Это будет ждать до 30 секунд, пока поток не закончится.
Thread t = new Thread() {
public void run() {
badExternalMethod();
synchronized (this) {
notifyAll();
}
}
};
synchronized (t) {
t.start();
try {
t.wait(30000); // 30 secs
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// t завершено или истекло время ожидания
Вы не сможете волшебным образом остановить работающую нить через 30 секунд; то, что вам нужно сделать, это заставить этот поток проверить некоторое состояние по истечении времени, заметить, что это заняло слишком много времени и return
из его метода запуска.
Есть примерно два подхода к этому:
- Сделайте так, чтобы поток вызова библиотеки выполнял свою работу в "чанках", каждый из которых занимает небольшое количество времени, и проверял состояние между каждым чанком. Например, если вы обрабатываете сотни тысяч записей, вы можете обработать несколько сотен в одном пакете, а затем установите флажок. Или, если вы делаете потенциально блокирующие вызовы с доступным временем ожидания, установите время ожидания на 500 мс и отметьте флаг между каждым вызовом.
- Пусть основной поток прерывает поток вызовов библиотеки, когда время истекло, и убедитесь, что поток библиотеки обрабатывает прерывания правильно и проверяет флаг, когда это так. Это потребовало бы, чтобы поток вызова библиотеки выполнял прерываемый метод, хотя любой потенциально длительный метод должен допускать прерывания.
В обоих случаях вам нужно, чтобы один из потоков (вероятно, основной поток, так как ему больше нечего делать) установил флаг "стоп" в true
когда время истекло (и эта переменная должна быть объявлена как volatile, чтобы обновления видели все потоки). Аналогично, когда поток вызова библиотеки видит этот флаг как истинный, он должен прекратить то, что он делает, обычно возвращаясь из метода run().
Вы не должны действительно убивать поток библиотеки из основного потока; Посмотрите, почему Thread.stop, Thread.suspend и Thread.resume устарели по причинам, и альтернатива, которая очень похожа на то, что я описал выше.:-)