2010-03-10 4 views
0

У меня есть код, который нужно сделать что-то вроде этогоJVM не выходит, когда TimeoutException происходит

Существует список классов каждый с каким-либо способом (позволяет сказать выполнить()). Мне нужно вызвать этот метод для каждого класса, и для каждого вызова есть фиксированное время. Теперь один из методов выполнения класса плохо написан и приводит к таймауту, из-за которого jvm не выходит. Я запускаю класс следующим образом.

java ExecutorServiceTest execute TestClass1 TestClass2 TestClass3 

Почему jvm не выходит после завершения выполнения кода?

я получаю следующие выходные данные

In class 1 
In Class 2 
java.util.concurrent.TimeoutException 
at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source) 
at java.util.concurrent.FutureTask.get(Unknown Source) 
at ExecutorServiceTest.main(ExecutorServiceTest.java:78) 
java.util.concurrent.TimeoutException 
at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source) 
at java.util.concurrent.FutureTask.get(Unknown Source) 

исполняют раз во второй класс, и в том, что после того, выполнять также раз третьего класса из. Почему тайм-аут третьего класса?

jvm не выходит после завершения выполнения. Какова причина? Также почему TestClass3 выполнить timedout?

import java.lang.reflect.Method; 
import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.List; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.concurrent.TimeUnit; 
import java.util.concurrent.TimeoutException; 

class Task implements Callable<String> { 
    Object instance; 
    Method m; 
    Object[] input; 
    Task(Object instance, Method m, Object[] input) { 
     this.instance = instance; 
     this.m = m; 
     this.input = input; 
    } 
    public String call() { 
     String s = "initial"; 
     try { 
      m.invoke(instance, input); 
     } 
     catch (RuntimeException e) { 
     } 
     catch (Exception e) { 
     } 
     finally { 

     } 
     return s; 
    } 
} 


public class ExecutorServiceTest { 
    public static void main(String[] args) { 
     String methodName = args[0]; 
     String className; 
     List<Object> instanceList = new ArrayList<Object>(); 
     for (int i=1;i<args.length;i++) { 
      className = args[i]; 
      Object o = null; 
      try { 
       o = Class.forName(className).newInstance(); 
      } catch (InstantiationException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IllegalAccessException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (ClassNotFoundException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      instanceList.add(o); 
     } 
     ExecutorService executor = Executors.newSingleThreadExecutor(); 
     Iterator<Object> iter = instanceList.iterator(); 
     while (iter.hasNext()) { 
      Object o = iter.next(); 
      Method m = null; 
      try { 
       m = o.getClass().getDeclaredMethod(methodName, new Class[] {}); 
      } catch (SecurityException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (NoSuchMethodException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      Task t = new Task(o,m,new Object[]{}); 
      Future<String> fut = executor.submit(t); 
      try { 
       fut.get(2,TimeUnit.SECONDS); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (ExecutionException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (TimeoutException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
     executor.shutdown(); 
    } 
} 


public class TestClass1 { 
    public void execute() { 
     System.out.println("In class 1"); 
    } 
} 


public class TestClass2 { 
    public void execute() { 
     System.out.println("In class 2"); 
     boolean b = true; 
     while (b) { 

     } 
    } 
} 


public class TestClass3 { 
    public void execute() { 
     System.out.println("In class 3"); 
    } 
} 

ответ

2

ExecutorService.shutdown() на самом деле не остановить все запущенные исполнители/темы, it just tells the service to stop accepting new tasks:

void shutdown()
Инициирует упорядоченное завершение работы, в котором выполняются ранее поставленные задачи, но новые задачи не принимаются. Invo катион не имеет дополнительного эффекта, если он уже выключен.

Ваш экземпляр TestClass2 никогда не остановится, потому что он имеет петлю while(true), которая никогда не останавливается.

Если вы хотите немедленно остановить ExecutorService, вы можете использовать awaitTermination(long timeout, TimeUnit unit) или shutdownNow().

+1

Оба утверждения не останавливают JVM. –

+0

Они не должны. Вы видели, как часть вашего TestInstance2 имеет бесконечный цикл? –

2

Вам нужно позвонить executor.shutdown() или создать демон нить (с помощью соответствующих ThreadFactory передается Executors.newSingleThreadExecutor()

+0

В коде отсутствует инструкция executor.shutdown(). Он не работает даже с этим заявлением. –