我想創建一個緩存線程池,但它作爲一個固定的線程池。目前,我有這樣的代碼:線程池不調整大小
public class BackgroundProcesses {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//ExecutorService threadPool2 = Executors.newCachedThreadPool();
ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
for (int i = 0; i < 800; i++) {
Callable<String> task = new Task();
threadPool.submit(task);
}
}
}
class Task implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " is ready");
return "";
}
}
如果我運行代碼,我得到的輸出:
pool-1-thread-1 is ready
pool-1-thread-2 is ready
pool-1-thread-1 is ready
pool-1-thread-2 is ready
...
含義只有2個線程正在做的各項工作,並沒有新的工作線程被添加到池中。如果任務在隊列中等待(最多10個),線程池不應該產生更多的線程?
我不想使用Executors.newCachedThreadPool()
,因爲它實際上沒有最大線程的上限,它有corePoolSize
0。我希望有一些線程隨時準備好以提高響應能力。
-----編輯1 -----
謝謝你阿列克謝的答案。將容量設置爲隊列使其表現得如預期的那樣,但是現在我遇到了一個新問題。
後臺任務的數量差別很大。大部分時間爲0,但在短時間內最多可以執行50個併發任務。什麼是處理這個問題的有效方法?請記住,大多數後臺任務都是短暫的(< 1秒),但也有一些長期任務(> 1分鐘)。
如果我把我的線程池像這樣:
ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
我將最有可能與峯值使用得到RejectedExecutionException。但是,如果我設置線程池像這樣:
ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200));
,則任何新的工作線程將永遠不會加入,因爲隊列不會最大程度的發揮。
CPU至少有4個內核,所以這在我看來是浪費。大多數情況下,根本沒有任何後臺任務(80%的正常運行時間),因此保留固定的線程池也是浪費的。
感謝您的理解。但是現在我得到了RejectedExecutionException(池大小= 10,活動線程= 10,排隊任務= 10),因爲隊列被填滿並且所有活動的線程都用完了。 –