2010-08-15 2 views
5

Я использую стороннюю библиотеку для обработки большого количества наборов данных. Процесс очень часто переходит в бесконечный цикл (или заблокирован - не знаю, почему и не может попасть в код). Я хотел бы убить это после установленного времени и продолжить следующий случай. Простым примером является:убивающий бесконечный цикл в java

for (Object data : dataList) { 
    Object result = TheirLibrary.processData(data); 
    store(result); 
} 

processData обычно занимает 1 секунду макс. Я хотел бы установить таймер, который убивает processData() после, скажем, 10 секунд

EDIT Я был бы признателен за фрагмент кода (я не практикован в использовании Threads). Подход Executor полезен, но я не совсем понимаю, с чего начать. Кроме того, псевдокод для более обычного подхода является слишком общим для меня для кодирования.

@Steven Schlansker - предполагает, что если приложение thirdparty не ожидает прерывания, оно не будет работать. Снова детали и примеры будут оценены

EDIT Я получил точное решение, которое я хотел от своих коллег Сэма Адамса, который я добавляю в качестве ответа. Он имеет более подробную информацию, чем другие ответы, но я дам им оба голоса. Я буду отмечать Сэма как утвержденный ответ

+1

Это определенно бесконечный цикл, или он может быть заблокирован? Профилирование закрытой библиотеки может помочь (если только она не будет устранена). –

+0

@ Jim Downing Да, это может быть заблокировано - не знаю, почему –

+0

это можно сделать в JMX? – amphibient

ответ

2

Сэм Адамс послал мне следующий ответ, который мой принял один

Thread thread = new Thread(myRunnableCode); 
thread.start(); 
thread.join(timeoutMs); 
if (thread.isAlive()) { 
    thread.interrupt(); 
} 

и myRunnableCode регулярно проверяют Thread.isInterrupted() и выходят чисто, если это возвращает истину.

В качестве альтернативы вы можете сделать:

Thread thread = new Thread(myRunnableCode); 
thread.start(); 
thread.join(timeoutMs); 
if (thread.isAlive()) { 
    thread.stop(); 
} 

Но этот метод не рекомендуется, так как это опасно.

http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#stop() «Этот метод является по сути небезопасен. Остановка нити с Thread.stop заставляет его разблокировать все мониторы, что она запертые (как естественное следствие, за исключение бесконтрольно ThreadDeath распространяющегося вверх по стеке). Если какие-либо объектов, ранее защищенных этими мониторами, находились в несогласованном состоянии, поврежденные объекты становятся видимыми для других потоков, что может привести к произвольному поведению ».

Я реализовал второе, и он делает то, что я хочу в данный момент.

+0

Второе решение (которое, как вы говорите, вы реализовали), совпадает с решением и комментарием, добавленным к Ответ schoetbi. –

+0

@ Ответ Jim Downing schoetbi был псевдокодом и не дал точных вызовов (например, «while (! all threads finished)» не дает реальных методов –

7

Положите вызов в библиотеку в другой поток и убейте эту тему после таймаута. Таким образом, вы также можете обрабатывать несколько объектов одновременно, если они не зависят друг от друга.


EDIT: Запрос Democode

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

for (Object data : dataList) { 
    Thread t = new LibThread(data); 
    // store the thread somewhere with an id 
    // tid and starting time tstart 
    // threads 
    t.start(); 
    } 

while(!all threads finished) 
{ 
    for (Thread t : threads) 
    { 
     // get start time of thread 
     // and check the timeout 
     if (runtime > timeout) 
     { 
      t.stop(); 
     } 
    } 
} 

class LibThread extends Thread { 
    Object data; 

    public TextThread(Object data) 
    { 
     this.data = data; 
    } 

    public void processData() 
    { 
     Object result = TheirLibrary.processData(data); 
     store(result); 
    } 
} 
+2

Вы избили меня - я удалил свой похожий ответ, но думаю, стоит упомянуть, что с помощью join (timeout) вы подождете достаточно долго ... –

+1

+1 за справедливость. Полоса пропускания - это все :-) – schoetbi

+0

Я был бы признателен за пример короткого кода (PeterMR) –

10

Одним из методов ExecutorService.invokeAll(...) берет тайм-аут аргумент. Создайте единую вызываемую, которая вызывает библиотеку, и переносит ее в список как аргумент этого метода. Будущее вернулось, указав, как оно прошло.

(Примечание: тестировался мной)

+0

Учитывая это +1, поскольку это был метод, о котором я собирался писать. Возможно, с некоторым кодом можно объяснить, как все это работает. Но определенно использование java.util.concurrent - способ сделать это. –

+1

Не стесняйтесь писать лучший ответ. –

+2

Если библиотека не справляется с прерываниями, вы, скорее всего, никогда не вернетесь из бесконечного цикла. :-( –