Pergunta

Eu tenho o código que precisa fazer algo como isto

Há uma lista de classes, cada uma com algum método (digamos execute ()). Eu preciso invocar esse método em cada classe e há um tempo limite fixo para cada invocação. Agora, um dos da classe executar método é mal escrito e resulta em um tempo limite devido a que a JVM não sair. Estou executando a classe como este.

java ExecutorServiceTest execute TestClass1 TestClass2 TestClass3

Por que a JVM não sair depois de completar a execução do código?

Eu recebo a seguinte saída

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)

O segundo da classe executam vezes fora e, depois disso, o terceiro da classe executar também expira. Por que a terceira classe de executar tempo?

A JVM não sair após a execução for concluída. Qual é a razão? Também porque é que o TestClass3 executar 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");
    }
}
Foi útil?

Solução

ExecutorService.shutdown() na verdade não parar qualquer correndo executores / threads, apenas informa ao serviço de parar de aceitar novas tarefas :

void shutdown()
Iniciados um desligamento ordenado em que as tarefas previamente submetidos são executados, mas há novas tarefas serão aceitos. Invocation não tem efeito adicional se já encerrado.

Seu exemplo TestClass2 nunca vai parar de correr porque tem um loop while(true) que nunca é interrompida.

Se você quiser parar o ExecutorService imediatamente, você pode usar awaitTermination(long timeout, TimeUnit unit) ou shutdownNow().

Outras dicas

Você precisa chamar executor.shutdown() ou criar uma linha daemon (usando ThreadFactory apropriado passado para Executors.newSingleThreadExecutor()

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top