4

我的代码有一个使用ExecutorService固定线程池实现的线程池。池执行的大多数任务都很短,但有时有一个任务会运行很长时间,大约 20-30 秒。此任务运行时,不会执行新任务,只有在长时间运行的任务完成后才会恢复。

池设置为 20,所以这不是问题,因为我可以只运行 2 个线程来重新创建它,第一个是长时间运行的,第二个被卡住了。

我一直在琢磨为什么它被卡住了,然后我切换newFixedThreadPool()newCachedThreadPool()并且瓶颈被释放了。这是我所做的唯一改变。

这种行为有意义吗?代码似乎运行良好,所以我想我会保留更改,据我所知,如果您正在运行许多短任务,最好使用缓存线程池,但我想知道为什么固定池会挂起并且在那里有办法解决吗?

此外,如果有的话,从固定切换到缓存可能会产生什么副作用?

谢谢。

4

1 回答 1

0

可能的结果是更多线程将同时运行,因为newCachedThreadPool()允许运行 Integer.MAX_VALUE 线程数。

如果不查看您的代码,很难猜测副作用。

但正如我认为的那样,如果通过增加线程数解决了一个问题,那么你很有可能拥有锁。

例如,您有 4 个资源 A、B、C、D。和 4 个任务:

1) 短任务A 需要资源A
2) 短任务B 需要资源B
3) 短任务C 需要资源C
4) 长任务D 需要资源A 和D

因此,在某一时刻,我们将遇到下一种情况:

Thread1: TaskA await for resource A
Thread2: TaskD has A and D and running

TaskB wait in Queue
TaskC wait in Queue

当您将 pull 更改为具有无限线程数的 pull 或具有许多允许线程的固定线程池时:

Thread1: TaskA await for resource A
Thread2: TaskD has A and D and running
Thread3: TaskB has resource B
Thread4: TaskC has resource C

因此,其中一个线程被另一个线程阻塞,但您看不到这一点,因为所有其他任务都是在没有锁的情况下执行的。

于 2013-06-27T17:48:50.550 回答