JVM не завершается, когда возникает TimeoutException - PullRequest
0 голосов
/ 10 марта 2010

У меня есть код, который должен сделать что-то вроде этого

Есть список классов, каждый с некоторым методом (скажем, execute ()).Мне нужно вызывать этот метод для каждого класса, и для каждого вызова существует фиксированный тайм-аут.Теперь один из методов исполнения класса написан плохо и приводит к тайм-ауту, из-за которого 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 время ожидания выполнения?

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 ]

2 голосов
/ 10 марта 2010

ExecutorService.shutdown() на самом деле не останавливает никаких запущенных исполнителей / потоков, просто говорит службе прекратить принимать новые задачи :

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

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

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

2 голосов
/ 10 марта 2010

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

...