目前我正在使用Executor服务创建固定线程池
executor = Executors.newFixedThreadPool(coreAmount);
虽然这很好,但我想知道是否可以保持创建多个线程的行为并更改最大池限制,以便如果所有线程都在使用中创建新线程并使用它而不是等待其中一个线程要终止的线程开始。
因此,例如,如果创建并正在使用8个线程,则第9个任务进入我希望它除了当前使用的8个线程之外还创建新线程。
似乎newCachedThreadPool()
有行为,但我也想要创建类似于newFixedThreadPool(int nThreads)
的线程数的能力
也许你可以使用ThreadPoolExecutor类。它是一个ExecutorService
,具有核心池数和最大池数的概念。它还具有其他功能,使其比Executors
返回的对象更具可定制性。
以下是一个例子。
int coreAmount = 8;
ExecutorService executor;
//executor = Executors.newFixedThreadPool(coreAmount);
int overrun = 4;
int maxWorkCount = 1_000;
executor = new ThreadPoolExecutor(coreAmount, coreAmount + overrun, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(maxWorkCount));
以下是有关上面示例中构造函数中传递的参数的更多信息。
corePoolSize - 池中保留的线程数,即使它们处于空闲状态,除非设置了allowCoreThreadTimeOut
maximumPoolSize - 池中允许的最大线程数
keepAliveTime - 当线程数大于核心时,这是多余空闲线程在终止之前等待新任务的最长时间。
unit - keepAliveTime参数的时间单位
workQueue - 在执行任务之前用于保存任务的队列。此队列将仅保存execute方法提交的Runnable任务。
就像你说的,缓存的线程池正是你正在寻找的。从它的documentation,
创建一个根据需要创建新线程的线程池,但在它们可用时将重用以前构造的线程。这些池通常会提高执行许多短期异步任务的程序的性能。如果可用,执行调用将重用先前构造的线程。如果没有可用的现有线程,则将创建一个新线程并将其添加到池中。未使用60秒的线程将终止并从缓存中删除。因此,长时间闲置的池不会消耗任何资源。
(重点:我的)
因此,例如,如果创建并正在使用8个线程,则第9个任务进入我希望它除了当前使用的8个线程之外还创建新线程。
从上面的文档中可以看出,Executors#newCachedThreadPool
就是这种情况。
如果您想模拟缓存的线程池,但是使用最少量的8
线程,可以使用以下内容:
ExecutorService service = new ThreadPoolExecutor(8, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
这在ThreadPoolExecutor中可用,使用Core Pool和Maximum Pool size值:从javadoc,您可以看到:
如果有多个corePoolSize但运行的maximumPoolSize线程少于maximumPoolSize,则只有在队列已满时才会创建新线程。
通过设置corePoolSize和maximumPoolSize,可以创建固定大小的线程池。
通过将maximumPoolSize设置为基本无限制的值(如Integer.MAX_VALUE),可以允许池容纳任意数量的并发任务。
最典型的情况是,核心和最大池大小仅在构造时设置,但也可以使用setCorePoolSize(int)和setMaximumPoolSize(int)动态更改。
因此,在您的示例中,您需要将'corePoolSize'设置为值8.然后,您需要设置'maximumPoolSize',然后将其作为池的上限。此外,与javadoc一样,这些值可以动态更改。