0

私はこのようなことをする必要があるコードを持っています

それぞれにいくつかのメソッド(execute()など)を持つクラスのリストがあります。各クラスでそのメソッドを呼び出す必要があり、呼び出しごとに固定のtimeOutがあります。現在、クラスのexecuteメソッドの1つが正しく記述されておらず、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)

2番目のクラスの実行がタイムアウトし、その後、3番目のクラスの実行もタイムアウトします。3番目のクラスの実行がタイムアウトするのはなぜですか?

実行が完了した後、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");
    }
}
4

2 に答える 2

2

ExecutorService.shutdown()実行中のエグゼキュータ/スレッドを実際に停止するのではなく、新しいタスクの受け入れを停止するようにサービスに指示するだけです

void shutdown()
以前に送信されたタスクが実行される正常なシャットダウンを開始しますが、新しいタスクは受け入れられません。すでにシャットダウンしている場合、呼び出しによる追加の効果はありません。

TestClass2インスタンスには、停止することのwhile(true)ないループがあるため、実行が停止することはありません。

ExecutorServiceをすぐに停止する場合は、awaitTermination(long timeout, TimeUnit unit)またはを使用できますshutdownNow()

于 2010-03-10T19:19:50.077 に答える
2

executor.shutdown()デーモンスレッドを呼び出すか作成する必要があります(適切なThreadFactoryパスを使用してExecutors.newSingleThreadExecutor()

于 2010-03-10T18:56:21.390 に答える