何时在ExecutorService中收集可运行的对象垃圾?

时间:2017-01-03 12:52:39

标签: java multithreading executorservice

我有一个可运行的对象A,它在实例化时与服务器交换心跳信号。我将这样的对象提交给具有固定线程池大小n的执行器服务。当run方法遇到异常时,它将返回。对于给定的情况,我的所有线程都遇到异常并返回,但创建的对象仍然存活并继续交换心跳信号。如何将这些对象标记为垃圾收集,以便它们能够阻止心跳信号的交换?

class A implements Runnable {
    public void run(){
          try{
           \\throws error
          } catch(Exception e){
            \\returns
          }
       }

    public static void main(){
          ExecutorService executor = Executors.newFixedThreadPool(n)
          for(i = 1 to n){
               A a = new A()
               executor.submit(a)
          }
       }
}

我应该在我的主管末尾放一个awaitTermination调用并返回吗?

修改
以其他方式提出问题,在所有线程返回后终止执行器服务的一种方法是在for循环之后调用shutdown()并使用Integer.MAX长秒调用awaitTermination,这大约是70年(这是一个时间限制我是不愿意强加)。还有其他选择吗?

3 个答案:

答案 0 :(得分:1)

  

在所有线程返回后终止执行器服务的一种方法是在for循环后调用shutdown()并用Integer.MAX调用awaitTermination,大约70年

正如文档所说,awaitTermination方法将阻止util:

  1. 关闭请求后所有任务都已完成执行
  2. 或发生超时,
  3. 或当前线程被中断,以先发生者为准

  4. 如此一旦三场比赛中的一场出现,它就会结束比赛,而不是等待70年。

答案 1 :(得分:0)

在池上调用shutdown()意味着池将不再接受任何新任务执行,但是当前的任务将不间断地运行。

调用awaitTermination(timeout)保持调用线程直到池完成,但是如果达到超时,则当前线程抛出execption,但它不会影响池中的任务。

如果runnable在线程池运行时抛出了未经处理的异常,则此runnable不再处于运行状态 - 线程池通常不会保留对此类对象的任何引用。

如果您使用FixedThreadPool,那么此池将创建任意数量的线程,并且在您在此池上调用shutdown()之前不会停止任何线程。

如果你没有引用抛出异常的runnable对象,那么它就像普通的未引用对象一样被收集垃圾。

如果你在线程池上调用shutdown()然后调用awaitTermination(),并且你的程序无论如何都不会停止,这意味着你的runnable的所有实例都没有抛出异常,有些仍然在运行从而阻止池完全关闭。

在java中你不能像那样杀死或停止运行线程(你只能使用例如。System.exit(0)杀死整个JVM,而不仅仅是选择线程),如果你需要这样的功能,你需要以一种允许你以某种方式与它进行通信的方式编程runnable的主体,即。使用一些" volatile boolean"变量,并且它将响应此变量值的变化 - 这意味着您需要添加"如果检查"这个变量在run()方法体中的值,它将在它应该返回时返回。

答案 2 :(得分:0)

任务执行完成后,任务本身都有资格进行垃圾回收。实际收集的时间和时间取决于垃圾收集器。

示例代码:

public class Main implements Runnable {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize");
    }

    @Override
    public void run() {
        try {
            throw new Exception("Error");
        } catch (Exception e) {
            //returns
        }
    }

    public static void main(String args[]) {
        int n = 8;
        ExecutorService executor = Executors.newFixedThreadPool(n);
        for (int i = 0 ; i < n; ++i) {
            Main a = new Main();
            executor.submit(a);
        }
        System.gc();
        System.out.println("end");
    }
}