我有一个可运行的对象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年(这是一个时间限制我是不愿意强加)。还有其他选择吗?
答案 0 :(得分:1)
在所有线程返回后终止执行器服务的一种方法是在for循环后调用shutdown()并用Integer.MAX调用awaitTermination,大约70年
正如文档所说,awaitTermination
方法将阻止util:
如此一旦三场比赛中的一场出现,它就会结束比赛,而不是等待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");
}
}