和我以前的Spring系列文章同樣,咱們會以作一些Demo作實驗的方式來複習一些知識點。
本文咱們先從Java併發中最最經常使用的線程池開始。java
首先咱們寫一個方法來每秒一次定時輸出線程池的基本信息:git
private void printStats(ThreadPoolExecutor threadPool){ Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { log.info("========================="); log.info("Pool Size: {}", threadPool.getPoolSize()); log.info("Active Threads: {}", threadPool.getActiveCount()); log.info("Number of Tasks Completed: {}", threadPool.getCompletedTaskCount()); log.info("Number of Tasks in Queue: {}", threadPool.getQueue().size()); log.info("========================="); }, 0, 1, TimeUnit.SECONDS); }
而後,咱們寫一個方法來定時提交任務到線程池:github
private void submitTasks(AtomicInteger atomicInteger, ThreadPoolExecutor threadPool) { IntStream.rangeClosed(1, 20).forEach(i -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } int id = atomicInteger.incrementAndGet(); threadPool.submit(() -> { log.info("{} started", id); try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } log.info("{} finished", id); }); }); }
能夠看到:緩存
如今咱們寫一個最普通的線程池,而且等待線程池全部任務執行完成:tomcat
@Test public void test1() throws InterruptedException { AtomicInteger atomicInteger = new AtomicInteger(); ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 2, 5, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)); printStats(threadPool); submitTasks(atomicInteger,threadPool); threadPool.shutdown(); threadPool.awaitTermination(1, TimeUnit.HOURS); }
能夠看到,這個線程池是:多線程
對於這樣的配置,你們想一下,任務提交過去後,線程池的工做方式是怎麼樣的?拋出幾個問題:併發
咱們執行後觀察一下輸出:app
09:51:37.709 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:37.715 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 0 09:51:37.718 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 0 09:51:37.718 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:37.718 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 0 09:51:37.718 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:38.705 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:38.705 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 0 09:51:38.705 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 0 09:51:38.705 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:38.705 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 0 09:51:38.705 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:38.716 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 1 started 09:51:39.701 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:39.701 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 1 09:51:39.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 1 09:51:39.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:39.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 0 09:51:39.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:39.718 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 2 started 09:51:40.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:40.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:40.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:40.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:40.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 0 09:51:40.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:41.701 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:41.701 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:41.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:41.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:41.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 1 09:51:41.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:42.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:42.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:42.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:42.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:42.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 2 09:51:42.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:43.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:43.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:43.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:43.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:43.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 3 09:51:43.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:44.701 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:44.701 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:44.701 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:44.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:44.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 4 09:51:44.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:45.702 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:45.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:45.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:45.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:45.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 5 09:51:45.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:46.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:46.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:46.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:46.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:46.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 6 09:51:46.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:47.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:47.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:47.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:47.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:47.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 7 09:51:47.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:48.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:48.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:48.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:48.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 09:51:48.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 8 09:51:48.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:48.719 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 1 finished 09:51:48.719 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 3 started 09:51:49.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:49.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:49.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:49.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 1 09:51:49.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 8 09:51:49.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:49.720 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 2 finished 09:51:49.720 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 4 started 09:51:50.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:50.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:50.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:50.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 2 09:51:50.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 8 09:51:50.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:51.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:51.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:51.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:51.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 2 09:51:51.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 9 09:51:51.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:52.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:52.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 09:51:52.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 09:51:52.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 2 09:51:52.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 10 09:51:52.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:52.749 [pool-1-thread-3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 15 started 09:51:53.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:53.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 3 09:51:53.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 3 09:51:53.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 2 09:51:53.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 10 09:51:53.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:53.754 [pool-1-thread-4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 16 started 09:51:54.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:54.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 4 09:51:54.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 4 09:51:54.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 2 09:51:54.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 10 09:51:54.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:54.755 [pool-1-thread-5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 17 started 09:51:55.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 09:51:55.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 09:51:55.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 09:51:55.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 2 09:51:55.703 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in queue: 10 09:51:55.704 [pool-2-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@fdefd3f[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@1a0dcaa[Wrapped task = me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest$$Lambda$50/0x0000000800105840@3bd40a57]] rejected from java.util.concurrent.ThreadPoolExecutor@d83da2e[Running, pool size = 5, active threads = 5, queued tasks = 10, completed tasks = 2] at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2055) at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:825) at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1355) at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118) at me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest.lambda$submitTasks$2(ThreadPoolExecutorTest.java:33) at java.base/java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:104) at java.base/java.util.stream.IntPipeline$Head.forEach(IntPipeline.java:593) at me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest.submitTasks(ThreadPoolExecutorTest.java:26) at me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest.test1(ThreadPoolExecutorTest.java:54) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
經過輸出能夠看到:less
咱們知道,Java的線程池默認狀況下是更傾向於使用隊列來存聽任務而不是傾向於使用更多的線程來消化任務,只有當隊列滿了以後纔會使用更多的線程池臨時處理一下突發的任務增多。
有的時候,咱們其實更但願的是更激進的方式,線程池優先開啓更多的線程,而是把隊列當成一個後備方案來使用。好比咱們這個例子,任務執行的很慢,須要10s,每秒提交一個任務,若是線程池能夠彈性到5個最大線程,那麼20秒後有5個任務在執行,5個任務已經完成,還有10個在線程池裏,這些任務最終均可以完成,而不是像以前由於線程池過晚擴張致使慢任務來不及處理。ide
咱們能夠經過Hack的方式來實現:
@Test public void test2() throws InterruptedException { AtomicInteger atomicInteger = new AtomicInteger(); BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(10) { @Override public boolean offer(Runnable e) { return false; } }; ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 2, 5, 5, TimeUnit.SECONDS, queue, new ThreadFactoryImpl("elastic-pool"), (r, executor) -> { try { executor.getQueue().put(r); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); threadPool.allowCoreThreadTimeOut(true); printStats(threadPool); submitTasks(atomicInteger,threadPool); threadPool.shutdown(); threadPool.awaitTermination(1, TimeUnit.HOURS); }
實現這個功能主要依靠兩個地方的改進:
咱們來看一下輸出:
10:53:37.889 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:37.898 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 0 10:53:37.901 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 0 10:53:37.901 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:37.901 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:53:37.901 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:38.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:38.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 0 10:53:38.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 0 10:53:38.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:38.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:53:38.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:38.919 [elastic-pool1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 1 started 10:53:39.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:39.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 1 10:53:39.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 1 10:53:39.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:39.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:53:39.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:39.924 [elastic-pool2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 2 started 10:53:40.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:40.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 10:53:40.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 10:53:40.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:40.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:53:40.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:40.930 [elastic-pool3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 3 started 10:53:41.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:41.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 3 10:53:41.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 3 10:53:41.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:41.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:53:41.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:41.934 [elastic-pool4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 4 started 10:53:42.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:42.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 4 10:53:42.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 4 10:53:42.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:42.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:53:42.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:42.935 [elastic-pool5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 5 started 10:53:43.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:43.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:43.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:43.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:43.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:53:43.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:44.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:44.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:44.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:44.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:44.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 1 10:53:44.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:45.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:45.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:45.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:45.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:45.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 2 10:53:45.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:46.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:46.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:46.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:46.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:46.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 3 10:53:46.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:47.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:47.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:47.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:47.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:47.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 4 10:53:47.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:48.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:48.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:48.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:48.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 0 10:53:48.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:53:48.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:48.921 [elastic-pool1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 1 finished 10:53:48.922 [elastic-pool1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 6 started 10:53:49.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:49.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:49.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:49.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 1 10:53:49.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:53:49.883 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:49.927 [elastic-pool2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 2 finished 10:53:49.928 [elastic-pool2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 7 started 10:53:50.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:50.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:50.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:50.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 2 10:53:50.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:53:50.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:50.933 [elastic-pool3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 3 finished 10:53:50.933 [elastic-pool3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 8 started 10:53:51.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:51.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:51.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:51.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 3 10:53:51.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:53:51.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:51.935 [elastic-pool4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 4 finished 10:53:51.935 [elastic-pool4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 9 started 10:53:52.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:52.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:52.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:52.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 4 10:53:52.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:53:52.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:52.937 [elastic-pool5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 5 finished 10:53:52.938 [elastic-pool5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 10 started 10:53:53.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:53.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:53.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:53.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 5 10:53:53.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:53:53.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:54.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:54.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:54.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:54.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 5 10:53:54.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 6 10:53:54.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:55.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:55.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:55.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:55.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 5 10:53:55.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 7 10:53:55.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:56.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:56.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:56.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:56.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 5 10:53:56.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 8 10:53:56.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:57.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:57.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:57.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:57.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 5 10:53:57.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 9 10:53:57.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:58.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:58.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:58.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:58.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 5 10:53:58.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 10 10:53:58.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:58.923 [elastic-pool1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 6 finished 10:53:58.923 [elastic-pool1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 11 started 10:53:59.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:59.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:53:59.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:53:59.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 6 10:53:59.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 9 10:53:59.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:53:59.931 [elastic-pool2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 7 finished 10:53:59.931 [elastic-pool2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 12 started 10:54:00.883 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:00.883 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:00.883 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:00.883 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 7 10:54:00.883 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 8 10:54:00.883 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:00.937 [elastic-pool3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 8 finished 10:54:00.938 [elastic-pool3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 13 started 10:54:01.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:01.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:01.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:01.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 8 10:54:01.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 7 10:54:01.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:01.937 [elastic-pool4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 9 finished 10:54:01.937 [elastic-pool4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 14 started 10:54:02.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:02.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:02.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:02.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 9 10:54:02.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 6 10:54:02.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:02.941 [elastic-pool5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 10 finished 10:54:02.941 [elastic-pool5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 15 started 10:54:03.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:03.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:03.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:03.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 10 10:54:03.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:54:03.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:04.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:04.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:04.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:04.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 10 10:54:04.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:54:04.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:05.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:05.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:05.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:05.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 10 10:54:05.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:54:05.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:06.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:06.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:06.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:06.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 10 10:54:06.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:54:06.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:07.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:07.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:07.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:07.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 10 10:54:07.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:54:07.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:08.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:08.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:08.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:08.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 10 10:54:08.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 5 10:54:08.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:08.927 [elastic-pool1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 11 finished 10:54:08.928 [elastic-pool1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 16 started 10:54:09.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:09.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:09.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:09.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 11 10:54:09.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 4 10:54:09.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:09.933 [elastic-pool2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 12 finished 10:54:09.933 [elastic-pool2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 17 started 10:54:10.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:10.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:10.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:10.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 12 10:54:10.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 3 10:54:10.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:10.942 [elastic-pool3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 13 finished 10:54:10.942 [elastic-pool3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 18 started 10:54:11.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:11.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:11.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:11.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 13 10:54:11.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 2 10:54:11.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:11.939 [elastic-pool4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 14 finished 10:54:11.939 [elastic-pool4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 19 started 10:54:12.881 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:12.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:12.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:12.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 14 10:54:12.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 1 10:54:12.882 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:12.946 [elastic-pool5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 15 finished 10:54:12.946 [elastic-pool5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 20 started 10:54:13.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:13.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:13.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:13.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 15 10:54:13.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:13.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:14.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:14.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:14.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:14.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 15 10:54:14.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:14.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:15.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:15.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:15.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:15.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 15 10:54:15.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:15.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:16.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:16.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:16.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:16.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 15 10:54:16.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:16.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:17.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:17.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:17.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:17.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 15 10:54:17.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:17.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:18.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:18.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 5 10:54:18.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 5 10:54:18.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 15 10:54:18.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:18.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:18.929 [elastic-pool1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 16 finished 10:54:19.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:19.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 4 10:54:19.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 4 10:54:19.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 16 10:54:19.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:19.880 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:19.938 [elastic-pool2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 17 finished 10:54:20.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:20.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 3 10:54:20.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 3 10:54:20.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 17 10:54:20.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:20.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:20.947 [elastic-pool3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 18 finished 10:54:21.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:21.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 2 10:54:21.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 2 10:54:21.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 18 10:54:21.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:21.879 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:21.943 [elastic-pool4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 19 finished 10:54:22.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:22.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Pool Size: 1 10:54:22.877 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Active Threads: 1 10:54:22.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks Completed: 19 10:54:22.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - Number of Tasks in Queue: 0 10:54:22.878 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - ========================= 10:54:22.950 [elastic-pool5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.ThreadPoolExecutorTest - 20 finished
從這個結果能夠看到:
其實,這裏還能夠想到另外一種思路,既然咱們但願在高併發的狀況下,線程池可以更積極建立線程,那麼咱們還能夠初始化線程池的時候就初始化5個核心線程,5個最大線程,而後開啓核心線程回收,這樣也能夠在併發低的時候節約線程。
固然這裏的這個實現很是簡單粗暴,其實何時隊列返回false是一種學問,咱們最好有必定的緩衝,不行的話再建立新的線程,也不必定就像這裏的直接返回false,後面咱們會提到tomcat線程池更好的實現。
在以前的測試中咱們使用到了一個自定義的線程工廠類來爲線程命名:
public class ThreadFactoryImpl implements ThreadFactory { private final AtomicLong threadIndex = new AtomicLong(0); private final String threadNamePrefix; private final boolean daemon; public ThreadFactoryImpl(final String threadNamePrefix) { this(threadNamePrefix, false); } public ThreadFactoryImpl(final String threadNamePrefix, boolean daemon) { this.threadNamePrefix = threadNamePrefix; this.daemon = daemon; } @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r, threadNamePrefix + this.threadIndex.incrementAndGet()); thread.setDaemon(daemon); return thread; } }
這是一個很是好的實踐,對於複雜的項目必定有N多個線程池,有了明確的容易識別的命名,更容易在出現問題的時候進行排查。
Tomcat線程池基於原生線程池作了一些改進,主要在三方面:
下面看下相關代碼:
首先是隊列這塊,咱們重點關注下重寫的offer方法,返回false來增長線程的時機:
@Slf4j public class TomcatTaskQueue extends LinkedBlockingQueue<Runnable> { private transient volatile TomcatThreadPool parent = null; public TomcatTaskQueue(int capacity) { super(capacity); } public void setParent(TomcatThreadPool tp) { parent = tp; } public boolean force(Runnable o) { if (parent == null || parent.isShutdown()) throw new RejectedExecutionException("taskQueue.notRunning"); return super.offer(o); //forces the item onto the queue, to be used if the task is rejected } public boolean force(Runnable o, long timeout, TimeUnit unit) throws InterruptedException { if (parent == null || parent.isShutdown()) throw new RejectedExecutionException("taskQueue.notRunning"); return super.offer(o, timeout, unit); //forces the item onto the queue, to be used if the task is rejected } @Override public boolean offer(Runnable o) { //we can't do any checks if (parent == null) return super.offer(o); //we are maxed out on threads, simply queue the object if (parent.getPoolSize() == parent.getMaximumPoolSize()) { log.info("pool==max, getPoolSize: {}, getMaximumPoolSize:{}, task:{}", parent.getPoolSize(), parent.getMaximumPoolSize(), o); return super.offer(o); } //we have idle threads, just add it to the queue if (parent.getSubmittedCount() <= (parent.getPoolSize())) { log.info("submit<=pool, getPoolSize: {}, getMaximumPoolSize:{}, task:{}", parent.getPoolSize(), parent.getMaximumPoolSize(), o); return super.offer(o); } //if we have less threads than maximum force creation of a new thread if (parent.getPoolSize() < parent.getMaximumPoolSize()) { log.info("Grow thread pool, getPoolSize: {}, getMaximumPoolSize:{}", parent.getPoolSize(), parent.getMaximumPoolSize()); return false; } //if we reached here, we need to add it to the queue log.info("else, getPoolSize: {}, getMaximumPoolSize:{}, task:{}", parent.getPoolSize(), parent.getMaximumPoolSize(), o); return super.offer(o); }
而後是線程池這塊,咱們重點注意出現拒絕異常後的處理策略:
@Slf4j public class TomcatThreadPool extends java.util.concurrent.ThreadPoolExecutor { /** * The number of tasks submitted but not yet finished. This includes tasks * in the queue and tasks that have been handed to a worker thread but the * latter did not start executing the task yet. * This number is always greater or equal to {@link #getActiveCount()}. */ private final AtomicInteger submittedCount = new AtomicInteger(0); public TomcatThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); prestartAllCoreThreads(); } public TomcatThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); prestartAllCoreThreads(); } public TomcatThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, new RejectHandler()); prestartAllCoreThreads(); } public TomcatThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, new RejectHandler()); prestartAllCoreThreads(); } public int getSubmittedCount() { return submittedCount.get(); } /** * {@inheritDoc} */ @Override public void execute(Runnable command) { execute(command, 0, TimeUnit.MILLISECONDS); } /** * Executes the given command at some time in the future. The command * may execute in a new thread, in a pooled thread, or in the calling * thread, at the discretion of the <tt>Executor</tt> implementation. * If no threads are available, it will be added to the work queue. * If the work queue is full, the system will wait for the specified * time and it throw a RejectedExecutionException if the queue is still * full after that. * * @param command the runnable task * @param timeout A timeout for the completion of the task * @param unit The timeout time unit * @throws RejectedExecutionException if this task cannot be * accepted for execution - the queue is full * @throws NullPointerException if command or unit is null */ public void execute(Runnable command, long timeout, TimeUnit unit) { submittedCount.incrementAndGet(); try { super.execute(command); } catch (RejectedExecutionException rx) { if (super.getQueue() instanceof TomcatTaskQueue) { final TomcatTaskQueue queue = (TomcatTaskQueue) super.getQueue(); try { if (!queue.force(command, timeout, unit)) { submittedCount.decrementAndGet(); throw new RejectedExecutionException("threadPoolExecutor.queueFull"); } else { log.warn("RejectedExecutionException throw, task {} put into queue again", command.toString()); } } catch (InterruptedException x) { submittedCount.decrementAndGet(); throw new RejectedExecutionException(x); } } else { submittedCount.decrementAndGet(); throw rx; } } } private static class RejectHandler implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, java.util.concurrent.ThreadPoolExecutor executor) { throw new RejectedExecutionException(); } } }
如今來寫一段測試代碼:
@Slf4j public class TomcatThreadPoolTest { @Test public void test() throws InterruptedException { TomcatTaskQueue taskqueue = new TomcatTaskQueue(5); TomcatThreadPool threadPool = new TomcatThreadPool(2, 5, 60, TimeUnit.SECONDS, taskqueue); taskqueue.setParent(threadPool); IntStream.rangeClosed(1, 10).forEach(i -> threadPool.execute(new Task(true, i))); IntStream.rangeClosed(1, 10).forEach(i -> threadPool.execute(new Task(false, i) , 1050, TimeUnit.MILLISECONDS)); threadPool.shutdown(); threadPool.awaitTermination(1, TimeUnit.HOURS); } @ToString class Task implements Runnable { private boolean slow; private String name; public Task(boolean slow, int index) { this.slow = slow; this.name = String.format("%s-%d", slow ? "slow" : "quick", index); } @Override public void run() { log.info("Start:{}", name); if (slow) { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } log.info("Finish:{}", name); } } }
在測試代碼中,咱們的隊列只有5,咱們的最大線程也是5,而咱們的慢任務是10個,由於咱們的任務容許等待1050ms嘗試提交到隊列,因此基於這樣的配置,咱們的快任務也能順利執行完成,而不會出錯:
16:38:36.117 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - submit<=pool, getPoolSize: 2, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=true, name=slow-1) 16:38:36.165 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-1 16:38:36.166 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - submit<=pool, getPoolSize: 2, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=true, name=slow-2) 16:38:36.166 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-2 16:38:36.166 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - Grow thread pool, getPoolSize: 2, getMaximumPoolSize:5 16:38:36.166 [pool-1-thread-3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-3 16:38:36.166 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - Grow thread pool, getPoolSize: 3, getMaximumPoolSize:5 16:38:36.167 [pool-1-thread-4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-4 16:38:36.167 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - Grow thread pool, getPoolSize: 4, getMaximumPoolSize:5 16:38:36.167 [pool-1-thread-5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-5 16:38:36.168 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=true, name=slow-6) 16:38:36.168 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=true, name=slow-7) 16:38:36.168 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=true, name=slow-8) 16:38:36.169 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=true, name=slow-9) 16:38:36.169 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=true, name=slow-10) 16:38:36.170 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-1) 16:38:37.169 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-2 16:38:37.169 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-1 16:38:37.169 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-7 16:38:37.169 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-6 16:38:37.169 [main] WARN me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPool - RejectedExecutionException throw, task TomcatThreadPoolTest.Task(slow=false, name=quick-1) put into queue again 16:38:37.169 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-2) 16:38:37.170 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-3) 16:38:37.170 [pool-1-thread-4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-4 16:38:37.170 [pool-1-thread-3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-3 16:38:37.170 [pool-1-thread-5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-5 16:38:37.170 [pool-1-thread-4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-8 16:38:37.170 [main] WARN me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPool - RejectedExecutionException throw, task TomcatThreadPoolTest.Task(slow=false, name=quick-3) put into queue again 16:38:37.170 [pool-1-thread-5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-10 16:38:37.170 [pool-1-thread-3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:slow-9 16:38:37.171 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-4) 16:38:37.171 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-5) 16:38:37.171 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-6) 16:38:38.171 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-7 16:38:38.171 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-6 16:38:38.172 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-1 16:38:38.172 [main] WARN me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPool - RejectedExecutionException throw, task TomcatThreadPoolTest.Task(slow=false, name=quick-6) put into queue again 16:38:38.172 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-2 16:38:38.172 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-1 16:38:38.172 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-2 16:38:38.172 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-3 16:38:38.172 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-4 16:38:38.172 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-3 16:38:38.172 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-4 16:38:38.172 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-5 16:38:38.172 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-7) 16:38:38.172 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-6 16:38:38.172 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-5 16:38:38.172 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-6 16:38:38.172 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-7 16:38:38.172 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-7 16:38:38.172 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-8) 16:38:38.173 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-8 16:38:38.173 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-8 16:38:38.173 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-9) 16:38:38.173 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-9 16:38:38.173 [pool-1-thread-1] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-9 16:38:38.173 [main] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatTaskQueue - pool==max, getPoolSize: 5, getMaximumPoolSize:5, task:TomcatThreadPoolTest.Task(slow=false, name=quick-10) 16:38:38.173 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Start:quick-10 16:38:38.174 [pool-1-thread-2] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:quick-10 16:38:38.175 [pool-1-thread-4] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-8 16:38:38.175 [pool-1-thread-3] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-9 16:38:38.175 [pool-1-thread-5] INFO me.josephzhu.javaconcurrenttest.concurrent.executors.TomcatThreadPoolTest - Finish:slow-10
注意日誌中出現了好幾回RejectedExecutionException,可是通過等待任務都提交到了隊列中。
咱們看看Executors預約義的兩種所謂經常使用的線程池:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
所謂固定大小的線程池就是線程大小固定,可是隊列是無界的。顯然,若是任務很是多很是慢超過了線程池的處理能力,產生了堆積,那麼這個無界隊列可能會致使OOM這是一個風險:
還有一種所謂緩存線程池,這個緩存意思是線程是緩存着用的,60秒回收,須要的話就建立,線程數量無上限,須要的話會一直建立。這個也很極端,可能會建立過多線程,一樣會致使OOM:
測試代碼就不給出了,你能夠本身作實驗。
因此阿里Java開發手冊不建議使用這兩種預約義的線程池,咱們應該本身根據須要控制線程池的:
這裏咱們給出官方的例子,經過實現自定義的beforeExecute來實現可暫停的線程池。
線程池代碼以下:
public class PausableThreadPoolExecutor extends ThreadPoolExecutor { private boolean isPaused; private ReentrantLock pauseLock = new ReentrantLock(); private Condition unpaused = pauseLock.newCondition(); public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); } public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); } public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); } public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); } @Override protected void beforeExecute(Thread t, Runnable r) { super.beforeExecute(t, r); pauseLock.lock(); try { while (isPaused) unpaused.await(); } catch (InterruptedException ie) { t.interrupt(); } finally { pauseLock.unlock(); } } public void pause() { pauseLock.lock(); try { isPaused = true; } finally { pauseLock.unlock(); } } public void resume() { pauseLock.lock(); try { isPaused = false; unpaused.signalAll(); } finally { pauseLock.unlock(); } } }
寫一段測試代碼試試:
@Test public void test() throws InterruptedException { PausableThreadPoolExecutor threadPool = new PausableThreadPoolExecutor(1,1,0,TimeUnit.HOURS,new LinkedBlockingQueue<>()); IntStream.rangeClosed(1, 5).forEach(i->threadPool.submit(()->{ try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } log.info("I'm done : {}", i); })); ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.schedule(threadPool::pause, 2, TimeUnit.SECONDS); scheduler.schedule(threadPool::resume, 4, TimeUnit.SECONDS); threadPool.shutdown(); threadPool.awaitTermination(1, TimeUnit.HOURS); }
在測試代碼中,咱們的線程池只有一個線程,咱們提交五個任務進去,每個任務須要執行1秒,咱們使用另外一個定時任務線程池來定時開關這個可暫停的線程池。運行結果以下:
能夠看到,這個線程池在2秒後暫停了4秒後恢復了。
在剛纔的測試中,咱們用到了定時任務線程池,這裏咱們再作一個測試。
咱們來測試一下scheduleAtFixedRate和scheduleWithFixedDelay的區別。
在下面的代碼裏,咱們分別進行兩次測試:
@Test public void test1() throws InterruptedException { AtomicInteger scheduleAtFixedRateTotal = new AtomicInteger(); ScheduledExecutorService scheduleAtFixedRateExecutorService = Executors.newSingleThreadScheduledExecutor(); ScheduledFuture scheduleAtFixedRateTotalFuture = scheduleAtFixedRateExecutorService.scheduleAtFixedRate(() -> { try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } log.info("scheduleAtFixedRate:" + scheduleAtFixedRateTotal.incrementAndGet()); }, 0, 100, TimeUnit.MILLISECONDS); scheduleAtFixedRateExecutorService.schedule(() -> scheduleAtFixedRateTotalFuture.cancel(false), 1, TimeUnit.SECONDS); while (!scheduleAtFixedRateTotalFuture.isDone()) TimeUnit.MILLISECONDS.sleep(1); Assert.assertEquals(11, scheduleAtFixedRateTotal.get()); AtomicInteger scheduleWithFixedDelayTotal = new AtomicInteger(); ScheduledExecutorService scheduleWithFixedDelayExecutorService = Executors.newSingleThreadScheduledExecutor(); ScheduledFuture scheduleWithFixedDelayFuture = scheduleWithFixedDelayExecutorService.scheduleWithFixedDelay(() -> { try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } log.info("scheduleWithFixedDelay:" + scheduleWithFixedDelayTotal.incrementAndGet()); }, 0, 100, TimeUnit.MILLISECONDS); scheduleWithFixedDelayExecutorService.schedule(() -> scheduleWithFixedDelayFuture.cancel(false), 1, TimeUnit.SECONDS); while (!scheduleWithFixedDelayFuture.isDone()) TimeUnit.MILLISECONDS.sleep(1); Assert.assertEquals(5, scheduleWithFixedDelayTotal.get()); }
經過斷言咱們也能夠知道,固定頻率執行任務"忽略"了任務執行的時間,因此能執行更屢次數,最終在1秒執行了11次。固定延遲執行任務是在任務完成後再延遲固定的間隔去執行,最終只能在1秒左右的時間執行5次。
下面是輸出:
在這裏,忽略兩個字,我打上了雙引號,那是由於對於單線程的定時任務線程池,任務若是執行太慢,比頻率還慢,那麼線程池也沒這個能力去fixRate執行。這裏你能夠嘗試一下把休眠時間100ms修改成200ms,從新運行後結果以下:
什麼?單元測試仍是經過的?難道不是應該運行了5次就結束了嗎?注意觀察,咱們的線程池並無在1秒後結束,而是維持了2秒多,仍是老問題,由於是單線程,咱們的關閉線程池的那個任務也沒法及時獲得執行。
嘗試修改代碼,把cancel任務放到獨立的線程池去執行:
Executors.newSingleThreadScheduledExecutor().schedule(() -> scheduleAtFixedRateTotalFuture.cancel(false), 1, TimeUnit.SECONDS);
(或者也可使用2個線程的定時任務線程池)
能夠看到,此次的結果符合預期:
從Java 1.8開始,Executors提供了newWorkStealingPool來得到一個ForkJoin線程池。
從命名能夠看到,這是一個工做竊取線程池,傳統的線程池具備公共的一個任務隊列,在任務不少,任務執行很快(CPU密集型任務)的狀況下,會發生比較多的競爭問題,而ForkJoin的話每個線程都有本身的任務隊列,若是本身的隊列沒有任務的話能夠從其它隊列竊取任務,這樣確保了吞吐的同時,減小了競爭。咱們寫一段代碼來比較一下:
@Slf4j public class ForkJoinPoolBenchmark { @Test public void test() throws InterruptedException { AtomicLong atomicLong = new AtomicLong(); StopWatch stopWatch = new StopWatch(); ExecutorService normal = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); ExecutorService forkjoin = Executors.newWorkStealingPool(Runtime.getRuntime().availableProcessors()); stopWatch.start("normal"); LongStream.rangeClosed(1, 10000000).forEach(__->normal.submit(atomicLong::incrementAndGet)); normal.shutdown(); normal.awaitTermination(1, TimeUnit.HOURS); stopWatch.stop(); long r = atomicLong.get(); stopWatch.start("forkjoin"); LongStream.rangeClosed(1, 10000000).forEach(__->forkjoin.submit(atomicLong::incrementAndGet)); forkjoin.shutdown(); forkjoin.awaitTermination(1, TimeUnit.HOURS); stopWatch.stop(); log.info(stopWatch.prettyPrint()); log.info("result:{},{}", r, atomicLong.get()); } }
在這裏,咱們的任務很簡單就是不斷++一個AtomicLong。測試結果以下:
能夠看到,很明顯forkjoin更快。
常常發現有一些小夥伴寫代碼,在把任務提交到線程池後,任務常常會出異常,出異常也無論,他們說沒事,線程池會捕獲異常的。真的是這樣嗎?寫段代碼試試:
@Slf4j public class ThreadPoolExceptionTest { @Before public void setDefaultUncaughtExceptionHandler(){ Thread.setDefaultUncaughtExceptionHandler((Thread t, Throwable e)->{ log.warn("Exception in thread {}", t,e); }); } @Test public void test() throws InterruptedException { String prefix = "test"; ExecutorService threadPool = Executors.newFixedThreadPool(1, new ThreadFactoryImpl(prefix)); IntStream.rangeClosed(1, 10).forEach(i -> threadPool.execute(() -> { if (i == 5) throw new RuntimeException("error"); log.info("I'm done : {}", i); if (i < 5) Assert.assertEquals(prefix + "1", Thread.currentThread().getName()); else Assert.assertEquals(prefix + "2", Thread.currentThread().getName()); })); threadPool.shutdown(); threadPool.awaitTermination(1, TimeUnit.HOURS); } }
在這裏咱們一共有10個任務,執行到第五個任務的時候,會主動拋出一個異常。
從斷言能夠看到,一開始的任務是在test1線程上執行的,由於出了異常後面的任務就在test2線程上執行了,看看運行結果:
結果上也能夠看到幾個結論:
不過這個結論不徹底正確,咱們嘗試把execute改成submit來試試:
@Test public void test() throws InterruptedException { String prefix = "test"; ExecutorService threadPool = Executors.newFixedThreadPool(1, new ThreadFactoryImpl(prefix)); List<Future> futures = new ArrayList<>(); IntStream.rangeClosed(1, 10).forEach(i -> futures.add(threadPool.submit(() -> { if (i == 5) throw new RuntimeException("error"); log.info("I'm done : {}", i); // if (i < 5) Assert.assertEquals(prefix + "1", Thread.currentThread().getName()); // else Assert.assertEquals(prefix + "2", Thread.currentThread().getName()); }))); for (Future future : futures) { try { future.get(); } catch (ExecutionException e) { log.warn("future ExecutionException",e); } } threadPool.shutdown(); threadPool.awaitTermination(1, TimeUnit.HOURS); }
輸出結果以下:
能夠看到此次不同了,異常會在Future.get()的時候拿到,所以線程也不會死亡。
咱們再寫一段代碼比較下性能(須要註釋setDefaultUncaughtExceptionHandler中的log.warn避免輸出異常):
@Test public void test2() throws InterruptedException { StopWatch stopWatch = new StopWatch(); ExecutorService threadPool1 = Executors.newFixedThreadPool(1); stopWatch.start("execute"); IntStream.rangeClosed(1, 100000).forEach(i->threadPool1.execute(()->{ throw new RuntimeException("error"); })); threadPool1.shutdown(); threadPool1.awaitTermination(1, TimeUnit.HOURS); stopWatch.stop(); ExecutorService threadPool2 = Executors.newFixedThreadPool(1); stopWatch.start("submit"); IntStream.rangeClosed(1, 100000).forEach(i->threadPool2.submit(()->{ throw new RuntimeException("error"); })); threadPool2.shutdown(); threadPool2.awaitTermination(1, TimeUnit.HOURS); stopWatch.stop(); log.info(stopWatch.prettyPrint()); }
結果以下:
這就更證明了以前說的從新建立線程的代價問題。你還能夠本身測試一下,定時任務線程池的任務出異常了會怎麼樣?
本文的全部代碼見個人Github Repo:https://github.com/JosephZhu1983/java-concurrent-test
代碼的測試基於JDK11
本文咱們作了十來個實驗,各類測試線程池。總結下來幾點: