我需要清理Java中的Thread对象吗?

时间:2019-10-09 07:28:44

标签: java multithreading concurrency runnable

在我的Java应用程序中,我有一个Runnable,例如:

this.runner = new Runnable({
    @Override
    public void run() {
        // do something that takes roughly 5 seconds.
    }
});

我大约需要每30秒(尽管这可能有所不同)在单独的线程中运行一次。代码的性质使我可以运行它,而不必理会它(无论成功还是失败)。我在我的应用程序中按以下一行代码执行以下操作:

(new Thread(this.runner)).start()

现在,这很好。但是,我想知道每个线程实例完成运行后是否应该进行某种清理?我正在VisualVM中对该应用程序进行CPU性能分析,并且可以看到,在1小时的运行时间过程中,正在创建许多线程。这种担忧有效吗?还是一切正常?

我启动new Thread而不是简单地将this.runner定义为Thread的原因是,有时我需要同时运行两次两次this.runner(在第一次运行调用结束之前) ,如果我将this.runner定义为Thread,我将无法执行此操作,因为单个Thread对象只能在初始执行完成后才能再次运行。

2 个答案:

答案 0 :(得分:2)

使用后需要“清理”或“关闭”的Java对象通常会实现AutoCloseable接口。这使得使用try-with-resources进行清理变得容易。 Thread类未实现AutoCloseable,并且没有“ close”或“ dispose”方法。因此,您无需进行任何显式清理。

但是

(new Thread(this.runner)).start()

不能保证立即开始计算Runnable。您可能不在乎它是成功还是失败,但是我想您 do 根本不在乎它是否运行。您可能希望限制同时运行的这些任务的数量。例如,您可能只希望一次运行。因此,您可能想要join()线程(或者也许是join with a timeout)。加入线程将确保线程将完成其计算。以超时方式加入线程会增加该线程开始计算的机会(因为当前线程将被挂起,从而释放可能运行另一个线程的CPU)。

但是,不建议创建多个线程来执行常规或频繁任务。您应该将submit任务添加到thread pool中。这样一来,您就可以控制最大的并发量,并为您提供其他好处(例如,优先处理不同的任务),并分摊expense of creating threads

您可以配置线程池以使用固定长度( bounded )任务队列,并在队列已满时导致向execute submitted tasks itself themselves提交线程。这样,您可以保证(最终)执行提交给线程池的任务。 ThreadPool.execute(Runnable)的文档说了

  

在将来的某个时间执行给定的任务

这表明该实现可以保证最终将运行所有已提交的任务 ,即使您不执行这些特定任务来确保已执行提交的任务。

答案 1 :(得分:1)

我建议您查看并发API。有许多通用的预定义方法。通过使用ExecutorService,您可以在将任务提交给执行者之后调用shutdown方法,该执行者停止接受新任务,等待先前提交的任务执行,然后终止执行者。 简短介绍: https://www.baeldung.com/java-executor-service-tutorial