有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

关于Executor服务的java澄清

我最近读到了关于将任务提交到ExecutorService的文章,其中的任务实现了Runnable接口。如果我错了,请纠正我的错误,但是:

  • 我的理解是,您可以创建一个ThreadPool,并具体定义这个池可以包含多少线程。这样做的原因是因为创建了一个缓存线程池,如果您向它提供太多任务,后者可能会崩溃吗?另外,我想知道,对于希望线程池包含的线程数,您可以传递的最大值是多少?什么能阻止我传递一个毫无意义的任意大整数,比如100000
  • 甚至使用ExecutorService的好处到底是什么?我知道它为您抽象了一些任务的实例化/处理,但我想除此之外,我对更深层次的理解不多

这是真的吗


共 (3) 个答案

  1. # 1 楼答案

    1. 启动线程很昂贵,应该尽可能避免。线程池缓存线程,这样就不那么频繁了

    2. 线程是一个有限的资源,您可以用尽,所以最好限制启动的最大数量。如果队列中的项目处理速度不够快,可以增加数量,但可以以可控的方式进行,这样就不会因为达到最大值而导致JVM崩溃。支持的最大值将由您使用的操作系统配置和硬件决定

    3. 我喜欢为整个应用程序创建一个单线程池,然后将其用于所有类型的后台工作。在web应用程序中,必须确保应用程序停止时线程结束。拥有一个单线程池使这变得容易。否则,由于忘记停止线程,您将经常遇到线程泄漏

    是的,我知道不建议在web应用程序中启动线程。只要你结束他们,对我来说没问题

  2. # 2 楼答案

    1. 存在固定线程池的原因是,您可能需要限制应用程序创建的线程数(并控制资源使用)。每个进程的线程数没有明确的限制,这取决于操作系统和主机(通常是内存)
    2. 使用executor服务的好处是,只需将一个实现替换为另一个实现,就可以改变多线程行为。比方说,只需在Executors上调用不同的方法,就可以从有限数量的线程切换到缓存的线程池,并且不需要更改代码
  3. # 3 楼答案

    回答你的第一点:

    It is my understanding that you can create a ThreadPool and specifically define how many threads this pool can contain. Is the reason for doing this over creating a cached thread pool that the latter can crash if you feed it too many tasks?

    ExecutorService有许多实现,比如newCachedThreadPool()newCachedThreadPool(ThreadFactory threadFactory)newFixedThreadPool(int nThreads),其中许多创建了缓存线程池,而许多没有,比如固定线程池固定线程池不是缓存线程池的替代品,但它们都是可选的
    因此,开发人员应该根据需求进行选择。如果你想完全控制线程池,那么就有一个固定大小的线程池,并且可以保证无论有多少任务,池中都只有那么多线程,这意味着在你的应用程序中只有那么多额外的线程

    Also, I am wondering, what is the maximum value you can pass in for the number of threads you want your thread pool to contain? What's to stop me from passing an arbitrarily large integer that makes no sense, say 100000?

    据我所知,对于你可以在线程池中放入多少线程,没有硬性规定。这实际上取决于JVM可以处理多少线程。例如,32位JVM可以处理的线程数少于64位JVM。因此,如果您使用的是64位JVM,那么您可以享受更多的奢侈
    没有什么能阻止开发人员输入一些无意义的数字,但这样做的后果是占用线程、性能下降、内存不足,甚至JVM崩溃

    回答你的第二点:

    What exactly is the benefit of even using an ExecutorService? I understand that it abstracts some of the instantiation/handling of your task for you, but I guess other than that I don't understand much more on a deeper level

    真正的优势来自这样一个事实,即您正在对接口进行编程。因此,您可以选择几个ExecutorService实现,比如ScheduledThreadPoolExecutorThreadPoolExecutor等等。此外,如果您使用ExecutorService等,您还可以选择许多其他选项

    • 在固定间隔后开始一个线程
    • 一次性调用任何任务,并让线程池执行它们

    阅读ScheduledThreadPoolExecutorThreadPoolExecutor中提供的方法,你会意识到它们提供的方法的威力

    希望这有帮助!


    编辑:基于@pens-fan-69的输入 阅读this article了解JVM可以支持多少线程


    堆栈大小

    整个JVM进程由Java线程组成,有些是内部JVM线程,如主线程、GC线程、终结器线程等,而有些是用户定义的线程

    无论它是内部线程还是用户定义的线程,每个线程都将有一部分堆栈分配给它以放置运行时信息JVM参数-Xss定义堆栈大小。例如,如果堆栈大小(-Xss)为64KB,则意味着JVM中的每个线程将有64KB来存储运行时信息。

    如果堆栈大小不足,则会引发堆栈溢出异常

    因此,JVM中可以存在的最大线程数将取决于堆栈大小堆栈大小越大,线程数越少,反之亦然

    默认堆栈大小因操作系统而异。下图: enter image description here