/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.kernel.concurrent; import com.liferay.portal.kernel.concurrent.test.MarkerBlockingJob; import com.liferay.portal.kernel.concurrent.test.TestUtil; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.ReentrantLock; import org.junit.Assert; import org.junit.Test; /** * @author Shuyang Zhou */ public class ThreadPoolExecutorTest { @Test public void testAdjustPoolSizeDecreaseCoreAndMaxPoolSizeAfterConstruct() { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 10, 20, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 10); Assert.assertEquals(10, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(20, threadPoolExecutor.getMaxPoolSize()); threadPoolExecutor.adjustPoolSize(5, 10); Assert.assertEquals(5, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(10, threadPoolExecutor.getMaxPoolSize()); } @Test public void testAdjustPoolSizeDecreaseCorePoolSizeToLessThanPoolSize() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 2, 3, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, false, 10); try { MarkerBlockingJob markerBlockingJob1 = new MarkerBlockingJob(true); MarkerBlockingJob markerBlockingJob2 = new MarkerBlockingJob(true); threadPoolExecutor.execute(markerBlockingJob1); threadPoolExecutor.execute(markerBlockingJob2); TestUtil.waitUntilBlock(markerBlockingJob1, markerBlockingJob2); TestUtil.unblock(markerBlockingJob1, markerBlockingJob2); TestUtil.waitUntilEnded(markerBlockingJob1, markerBlockingJob2); Assert.assertEquals(2, threadPoolExecutor.getPoolSize()); Assert.assertEquals(0, threadPoolExecutor.getActiveCount()); threadPoolExecutor.adjustPoolSize(1, 3); Assert.assertEquals(1, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(3, threadPoolExecutor.getMaxPoolSize()); Thread.sleep(TestUtil.KEEPALIVE_WAIT * 2); Assert.assertEquals(1, threadPoolExecutor.getPoolSize()); Assert.assertEquals(0, threadPoolExecutor.getActiveCount()); } finally { TestUtil.closePool(threadPoolExecutor); } } @Test public void testAdjustPoolSizeDecreseCoreAndMaxPoolSizeToLessThanPoolSize() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 2, 3, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, false, 10); try { MarkerBlockingJob markerBlockingJob1 = new MarkerBlockingJob(true); MarkerBlockingJob markerBlockingJob2 = new MarkerBlockingJob(true); MarkerBlockingJob markerBlockingJob3 = new MarkerBlockingJob(true); threadPoolExecutor.execute(markerBlockingJob1); threadPoolExecutor.execute(markerBlockingJob2); threadPoolExecutor.execute(markerBlockingJob3); TestUtil.waitUntilBlock( markerBlockingJob1, markerBlockingJob2, markerBlockingJob3); TestUtil.unblock( markerBlockingJob1, markerBlockingJob2, markerBlockingJob3); TestUtil.waitUntilEnded( markerBlockingJob1, markerBlockingJob2, markerBlockingJob3); Thread.sleep(TestUtil.SHORT_WAIT); Assert.assertEquals(3, threadPoolExecutor.getPoolSize()); Assert.assertEquals(0, threadPoolExecutor.getActiveCount()); Thread.sleep(TestUtil.KEEPALIVE_WAIT * 2); Assert.assertEquals(2, threadPoolExecutor.getPoolSize()); Assert.assertEquals(0, threadPoolExecutor.getActiveCount()); threadPoolExecutor.adjustPoolSize(1, 1); Assert.assertEquals(1, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(1, threadPoolExecutor.getMaxPoolSize()); Thread.sleep(TestUtil.KEEPALIVE_WAIT * 2); Assert.assertEquals(1, threadPoolExecutor.getPoolSize()); Assert.assertEquals(0, threadPoolExecutor.getActiveCount()); } finally { TestUtil.closePool(threadPoolExecutor); } } @Test public void testAdjustPoolSizeIllegalArgumentExceptions() { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 5, 10, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 10); try { threadPoolExecutor.adjustPoolSize(-1, 10); Assert.fail(); } catch (IllegalArgumentException iae) { } threadPoolExecutor = new ThreadPoolExecutor( 5, 10, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 10); try { threadPoolExecutor.adjustPoolSize(1, -1); Assert.fail(); } catch (IllegalArgumentException iae) { } threadPoolExecutor = new ThreadPoolExecutor( 5, 10, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 10); try { threadPoolExecutor.adjustPoolSize(1, 0); Assert.fail(); } catch (IllegalArgumentException iae) { } threadPoolExecutor = new ThreadPoolExecutor( 5, 10, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 10); try { threadPoolExecutor.adjustPoolSize(2, 1); Assert.fail(); } catch (IllegalArgumentException iae) { } } @Test public void testAdjustPoolSizeIncreaseCoreAndMaxPoolSizeAfterConstruct() { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 5, 10, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 10); Assert.assertEquals(5, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(10, threadPoolExecutor.getMaxPoolSize()); threadPoolExecutor.adjustPoolSize(10, 20); Assert.assertEquals(10, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(20, threadPoolExecutor.getMaxPoolSize()); } @Test public void testAdjustPoolSizeIncreaseCoreAndMaxPoolSizeWithEmptyTaskQueue() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, false, 10); try { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob(true); threadPoolExecutor.execute(markerBlockingJob); markerBlockingJob.waitUntilBlock(); Assert.assertEquals(1, threadPoolExecutor.getPoolSize()); Assert.assertEquals(1, threadPoolExecutor.getActiveCount()); threadPoolExecutor.adjustPoolSize(2, 2); Assert.assertEquals(2, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(2, threadPoolExecutor.getMaxPoolSize()); Thread.sleep(TestUtil.SHORT_WAIT); Assert.assertEquals(1, threadPoolExecutor.getPoolSize()); Assert.assertEquals(1, threadPoolExecutor.getActiveCount()); } finally { TestUtil.closePool(threadPoolExecutor, true); } } @Test public void testAdjustPoolSizeIncreaseCoreAndMaxPoolSizeWithNonEmptyTaskQueue() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, false, 10); try { MarkerBlockingJob markerBlockingJob1 = new MarkerBlockingJob(true); MarkerBlockingJob markerBlockingJob2 = new MarkerBlockingJob(true); threadPoolExecutor.execute(markerBlockingJob1); threadPoolExecutor.execute(markerBlockingJob2); markerBlockingJob1.waitUntilBlock(); Assert.assertEquals(1, threadPoolExecutor.getPoolSize()); Assert.assertEquals(1, threadPoolExecutor.getActiveCount()); Assert.assertEquals(1, threadPoolExecutor.getPendingTaskCount()); threadPoolExecutor.adjustPoolSize(2, 2); Assert.assertEquals(2, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(2, threadPoolExecutor.getMaxPoolSize()); markerBlockingJob2.waitUntilBlock(); Assert.assertEquals(2, threadPoolExecutor.getPoolSize()); Assert.assertEquals(2, threadPoolExecutor.getActiveCount()); Assert.assertEquals(0, threadPoolExecutor.getPendingTaskCount()); } finally { TestUtil.closePool(threadPoolExecutor, true); } } @Test public void testAutoResizePoolAllowCoreThreadTimeout() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 5, 10, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 10); try { Queue<MarkerBlockingJob> markerBlockingJobQueue = new LinkedList<>(); Assert.assertEquals(0, threadPoolExecutor.getPoolSize()); for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob( true); markerBlockingJobQueue.add(markerBlockingJob); threadPoolExecutor.execute(markerBlockingJob); markerBlockingJob.waitUntilBlock(); Assert.assertEquals(i + 1, threadPoolExecutor.getPoolSize()); Assert.assertEquals( i + 1, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals(i + 1, threadPoolExecutor.getTaskCount()); } for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob( true); markerBlockingJobQueue.add(markerBlockingJob); threadPoolExecutor.execute(markerBlockingJob); Assert.assertEquals(10, threadPoolExecutor.getPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals( i + 1, threadPoolExecutor.getPendingTaskCount()); Assert.assertEquals(i + 11, threadPoolExecutor.getTaskCount()); } for (int i = 0; i < 10; i++) { try { threadPoolExecutor.execute(new MarkerBlockingJob(true)); Assert.fail(); } catch (RejectedExecutionException ree) { } Assert.assertEquals(10, threadPoolExecutor.getPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getPendingTaskCount()); Assert.assertEquals(20, threadPoolExecutor.getTaskCount()); } Assert.assertEquals(20, markerBlockingJobQueue.size()); for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = markerBlockingJobQueue.remove(); markerBlockingJob.unBlock(); TestUtil.waitUntilEnded(markerBlockingJob); Assert.assertEquals(10, threadPoolExecutor.getPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals( 9 - i, threadPoolExecutor.getPendingTaskCount()); Assert.assertEquals(20, threadPoolExecutor.getTaskCount()); Assert.assertEquals( i + 1, threadPoolExecutor.getCompletedTaskCount()); } for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = markerBlockingJobQueue.remove(); markerBlockingJob.unBlock(); TestUtil.waitUntilEnded(markerBlockingJob); Thread.sleep(TestUtil.KEEPALIVE_WAIT); Assert.assertEquals(9 - i, threadPoolExecutor.getPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals( 0, threadPoolExecutor.getPendingTaskCount()); Assert.assertEquals(20, threadPoolExecutor.getTaskCount()); Assert.assertEquals( i + 11, threadPoolExecutor.getCompletedTaskCount()); } } finally { TestUtil.closePool(threadPoolExecutor, true); } } @Test public void testAutoResizePoolDoNotAllowCoreThreadTimeout() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 5, 10, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, false, 10); try { Queue<MarkerBlockingJob> markerBlockingJobQueue = new LinkedList<>(); Assert.assertEquals(0, threadPoolExecutor.getPoolSize()); for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob( true); markerBlockingJobQueue.add(markerBlockingJob); threadPoolExecutor.execute(markerBlockingJob); markerBlockingJob.waitUntilBlock(); Assert.assertEquals(i + 1, threadPoolExecutor.getPoolSize()); Assert.assertEquals( i + 1, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals(i + 1, threadPoolExecutor.getTaskCount()); } for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob( true); markerBlockingJobQueue.add(markerBlockingJob); threadPoolExecutor.execute(markerBlockingJob); Assert.assertEquals(10, threadPoolExecutor.getPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals( i + 1, threadPoolExecutor.getPendingTaskCount()); Assert.assertEquals(i + 11, threadPoolExecutor.getTaskCount()); } for (int i = 0; i < 10; i++) { try { threadPoolExecutor.execute(new MarkerBlockingJob(true)); Assert.fail(); } catch (RejectedExecutionException ree) { } Assert.assertEquals(10, threadPoolExecutor.getPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getPendingTaskCount()); Assert.assertEquals(20, threadPoolExecutor.getTaskCount()); } Assert.assertEquals(20, markerBlockingJobQueue.size()); for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = markerBlockingJobQueue.remove(); markerBlockingJob.unBlock(); TestUtil.waitUntilEnded(markerBlockingJob); Assert.assertEquals(10, threadPoolExecutor.getPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals( 9 - i, threadPoolExecutor.getPendingTaskCount()); Assert.assertEquals(20, threadPoolExecutor.getTaskCount()); Assert.assertEquals( i + 1, threadPoolExecutor.getCompletedTaskCount()); } for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = markerBlockingJobQueue.remove(); markerBlockingJob.unBlock(); TestUtil.waitUntilEnded(markerBlockingJob); Thread.sleep(TestUtil.KEEPALIVE_WAIT); Assert.assertEquals( (i > 4) ? 5 : 9 - i, threadPoolExecutor.getPoolSize()); Assert.assertEquals( 10, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals( 0, threadPoolExecutor.getPendingTaskCount()); Assert.assertEquals(20, threadPoolExecutor.getTaskCount()); Assert.assertEquals( i + 11, threadPoolExecutor.getCompletedTaskCount()); } } finally { TestUtil.closePool(threadPoolExecutor, true); } } @Test public void testAwaitTerminationSuccess() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, 1, TimeUnit.SECONDS, true, 3); threadPoolExecutor.shutdown(); long startTime = System.currentTimeMillis(); Assert.assertTrue( threadPoolExecutor.awaitTermination(10, TimeUnit.MILLISECONDS)); long waitTime = System.currentTimeMillis() - startTime; Assert.assertTrue(waitTime < TestUtil.SHORT_WAIT); } @Test public void testAwaitTerminationWithNegativeWaitTime() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3); long startTime = System.currentTimeMillis(); Assert.assertFalse( threadPoolExecutor.awaitTermination(-1, TimeUnit.MILLISECONDS)); long waitTime = System.currentTimeMillis() - startTime; Assert.assertTrue(waitTime < TestUtil.SHORT_WAIT); } @Test public void testAwaitTerminationWithoutShutdown() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3); long startTime = System.nanoTime(); Assert.assertFalse( threadPoolExecutor.awaitTermination( TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS)); long waitTime = System.nanoTime() - startTime; Assert.assertTrue( waitTime >= TimeUnit.MILLISECONDS.toNanos(TestUtil.KEEPALIVE_TIME)); } @Test public void testAwaitTerminationWithZeroWaitTime() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3); long startTime = System.currentTimeMillis(); Assert.assertFalse( threadPoolExecutor.awaitTermination(0, TimeUnit.MILLISECONDS)); long waitTime = System.currentTimeMillis() - startTime; Assert.assertTrue(waitTime < TestUtil.SHORT_WAIT); } @Test public void testConstructor1() { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 2); Assert.assertEquals(1, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(2, threadPoolExecutor.getMaxPoolSize()); Assert.assertEquals( 60 * 1000000000L, threadPoolExecutor.getKeepAliveTime(TimeUnit.NANOSECONDS)); Assert.assertEquals( false, threadPoolExecutor.isAllowCoreThreadTimeout()); Assert.assertEquals( Integer.MAX_VALUE, threadPoolExecutor.getRemainingTaskQueueCapacity()); RejectedExecutionHandler rejectedExecutionHandler = threadPoolExecutor.getRejectedExecutionHandler(); Assert.assertTrue(rejectedExecutionHandler instanceof AbortPolicy); ThreadPoolHandler threadPoolHandler = threadPoolExecutor.getThreadPoolHandler(); Assert.assertTrue( threadPoolHandler instanceof ThreadPoolHandlerAdapter); Assert.assertFalse(threadPoolExecutor.isShutdown()); Assert.assertFalse(threadPoolExecutor.isTerminating()); Assert.assertFalse(threadPoolExecutor.isTerminated()); } @Test public void testConstructor2() { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3); Assert.assertEquals(1, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(2, threadPoolExecutor.getMaxPoolSize()); Assert.assertEquals( TestUtil.KEEPALIVE_TIME * 1000000, threadPoolExecutor.getKeepAliveTime(TimeUnit.NANOSECONDS)); Assert.assertEquals( true, threadPoolExecutor.isAllowCoreThreadTimeout()); Assert.assertEquals( 3, threadPoolExecutor.getRemainingTaskQueueCapacity()); RejectedExecutionHandler rejectedExecutionHandler = threadPoolExecutor.getRejectedExecutionHandler(); Assert.assertTrue(rejectedExecutionHandler instanceof AbortPolicy); ThreadPoolHandler threadPoolHandler = threadPoolExecutor.getThreadPoolHandler(); Assert.assertTrue( threadPoolHandler instanceof ThreadPoolHandlerAdapter); Assert.assertFalse(threadPoolExecutor.isShutdown()); Assert.assertFalse(threadPoolExecutor.isTerminating()); Assert.assertFalse(threadPoolExecutor.isTerminated()); } @Test public void testConstructor3() { RejectedExecutionHandler rejectedExecutionHandler = new CallerRunsPolicy(); ThreadFactory threadFactory = Executors.defaultThreadFactory(); ThreadPoolHandler threadPoolHandler = new ThreadPoolHandlerAdapter(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3, rejectedExecutionHandler, threadFactory, threadPoolHandler); Assert.assertEquals(1, threadPoolExecutor.getCorePoolSize()); Assert.assertEquals(2, threadPoolExecutor.getMaxPoolSize()); Assert.assertEquals( TestUtil.KEEPALIVE_TIME * 1000000, threadPoolExecutor.getKeepAliveTime(TimeUnit.NANOSECONDS)); Assert.assertEquals( true, threadPoolExecutor.isAllowCoreThreadTimeout()); Assert.assertEquals( 3, threadPoolExecutor.getRemainingTaskQueueCapacity()); Assert.assertSame( rejectedExecutionHandler, threadPoolExecutor.getRejectedExecutionHandler()); Assert.assertSame(threadFactory, threadPoolExecutor.getThreadFactory()); Assert.assertSame( threadPoolHandler, threadPoolExecutor.getThreadPoolHandler()); Assert.assertFalse(threadPoolExecutor.isShutdown()); Assert.assertFalse(threadPoolExecutor.isTerminating()); Assert.assertFalse(threadPoolExecutor.isTerminated()); } @Test public void testConstructorExceptions() { try { new ThreadPoolExecutor( -1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1); Assert.fail(); } catch (IllegalArgumentException iae) { } try { new ThreadPoolExecutor( 1, -1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1); Assert.fail(); } catch (IllegalArgumentException iae) { } try { new ThreadPoolExecutor( 1, 0, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1); Assert.fail(); } catch (IllegalArgumentException iae) { } try { new ThreadPoolExecutor( 2, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1); Assert.fail(); } catch (IllegalArgumentException iae) { } try { new ThreadPoolExecutor(1, 1, -1, TimeUnit.MILLISECONDS, true, 1); Assert.fail(); } catch (IllegalArgumentException iae) { } try { new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, -1); Assert.fail(); } catch (IllegalArgumentException iae) { } try { new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 0); Assert.fail(); } catch (IllegalArgumentException iae) { } try { new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1, null, Executors.defaultThreadFactory(), new ThreadPoolHandlerAdapter()); Assert.fail(); } catch (NullPointerException npe) { } try { new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1, new AbortPolicy(), null, new ThreadPoolHandlerAdapter()); Assert.fail(); } catch (NullPointerException npe) { } try { new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1, new AbortPolicy(), Executors.defaultThreadFactory(), null); Assert.fail(); } catch (NullPointerException npe) { } } @Test public void testExecuteAcceptedOnConcurrentShutdown() throws InterruptedException { RecordRejectedExecutionHandler recordRejectedExecutionHandler = new RecordRejectedExecutionHandler(); final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3, recordRejectedExecutionHandler, Executors.defaultThreadFactory(), new ThreadPoolHandlerAdapter()); final TaskQueue<Runnable> taskQueue = threadPoolExecutor.getTaskQueue(); final CountDownLatch executeLatch = new CountDownLatch(1); Thread thread = new Thread() { @Override public void run() { try { ReentrantLock takeLock = taskQueue.getTakeLock(); takeLock.lock(); executeLatch.countDown(); try { while (!takeLock.hasQueuedThreads()) { Thread.sleep(1); } Assert.assertNotNull(taskQueue.take()); threadPoolExecutor.shutdown(); } finally { takeLock.unlock(); } } catch (InterruptedException ie) { } } }; thread.start(); executeLatch.await(); try { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob(); threadPoolExecutor.execute(markerBlockingJob); Assert.assertTrue( recordRejectedExecutionHandler.getRejectedList().isEmpty()); } finally { TestUtil.closePool(threadPoolExecutor); } } @Test public void testExecuteAfterShutdown() { RecordRejectedExecutionHandler recordRejectedExecutionHandler = new RecordRejectedExecutionHandler(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3, recordRejectedExecutionHandler, Executors.defaultThreadFactory(), new ThreadPoolHandlerAdapter()); threadPoolExecutor.shutdown(); MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob(); threadPoolExecutor.execute(markerBlockingJob); Assert.assertFalse(markerBlockingJob.isStarted()); List<Runnable> rejectedList = recordRejectedExecutionHandler.getRejectedList(); Assert.assertEquals(rejectedList.toString(), 1, rejectedList.size()); Assert.assertSame(markerBlockingJob, rejectedList.get(0)); } @Test public void testExecuteAfterTaskQueuePollingTimeoutBeforeExitChecking() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1); MarkerBlockingJob markerBlockingJob1 = new MarkerBlockingJob(true); threadPoolExecutor.execute(markerBlockingJob1); markerBlockingJob1.waitUntilBlock(); ReentrantLock mainLock = threadPoolExecutor.getMainLock(); TaskQueue<Runnable> taskQueue = threadPoolExecutor.getTaskQueue(); ReentrantLock takeLock = taskQueue.getTakeLock(); takeLock.lock(); try { markerBlockingJob1.unBlock(); while (!takeLock.hasQueuedThreads()) { Thread.sleep(1); } mainLock.lock(); } finally { takeLock.unlock(); } MarkerBlockingJob markerBlockingJob2 = new MarkerBlockingJob(true); try { while (!mainLock.hasQueuedThreads()) { Thread.sleep(1); } threadPoolExecutor.execute(markerBlockingJob2); } finally { mainLock.unlock(); } markerBlockingJob2.waitUntilBlock(); markerBlockingJob2.unBlock(); TestUtil.closePool(threadPoolExecutor); Assert.assertTrue(markerBlockingJob2.isEnded()); } @Test public void testExecuteFastConsumerSlowProducerAllowCoreThreadTimeout() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3); try { Assert.assertEquals(0, threadPoolExecutor.getActiveCount()); Assert.assertEquals(0, threadPoolExecutor.getPoolSize()); for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob(); threadPoolExecutor.execute(markerBlockingJob); markerBlockingJob.waitUntilEnded(); Thread.sleep(TestUtil.KEEPALIVE_WAIT); Assert.assertTrue(markerBlockingJob.isEnded()); Assert.assertEquals(0, threadPoolExecutor.getActiveCount()); Assert.assertEquals(0, threadPoolExecutor.getPoolSize()); Assert.assertEquals( i + 1, threadPoolExecutor.getCompletedTaskCount()); } } finally { TestUtil.closePool(threadPoolExecutor); } } @Test public void testExecuteFastConsumerSlowProducerDoNotAllowCoreThreadTimeout() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, false, 3); try { Assert.assertEquals(0, threadPoolExecutor.getActiveCount()); Assert.assertEquals(0, threadPoolExecutor.getPoolSize()); for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob(); threadPoolExecutor.execute(markerBlockingJob); markerBlockingJob.waitUntilEnded(); Thread.sleep(TestUtil.KEEPALIVE_WAIT); Assert.assertTrue(markerBlockingJob.isEnded()); Assert.assertEquals(0, threadPoolExecutor.getActiveCount()); Assert.assertEquals(1, threadPoolExecutor.getPoolSize()); Assert.assertEquals( i + 1, threadPoolExecutor.getCompletedTaskCount()); } } finally { TestUtil.closePool(threadPoolExecutor); } } @Test public void testExecuteNullRunnable() { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3); try { threadPoolExecutor.execute(null); Assert.fail(); } catch (NullPointerException npe) { } finally { TestUtil.closePool(threadPoolExecutor); } } @Test public void testExecuteRejectedOnConcurrentShutdown() throws InterruptedException { RecordRejectedExecutionHandler recordRejectedExecutionHandler = new RecordRejectedExecutionHandler(); final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3, recordRejectedExecutionHandler, Executors.defaultThreadFactory(), new ThreadPoolHandlerAdapter()); final TaskQueue<Runnable> taskQueue = threadPoolExecutor.getTaskQueue(); final CountDownLatch executeLatch = new CountDownLatch(1); Thread thread = new Thread() { @Override public void run() { try { ReentrantLock putLock = taskQueue.getPutLock(); putLock.lock(); executeLatch.countDown(); try { while (!putLock.hasQueuedThreads()) { Thread.sleep(1); } threadPoolExecutor.shutdown(); } finally { putLock.unlock(); } } catch (InterruptedException ie) { } } }; thread.start(); executeLatch.await(); try { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob(); threadPoolExecutor.execute(markerBlockingJob); List<Runnable> rejectedList = recordRejectedExecutionHandler.getRejectedList(); Assert.assertEquals( rejectedList.toString(), 1, rejectedList.size()); Assert.assertSame(markerBlockingJob, rejectedList.get(0)); Assert.assertFalse(markerBlockingJob.isStarted()); } finally { TestUtil.closePool(threadPoolExecutor); } } @Test public void testExecuteSuccess() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3); try { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob(); threadPoolExecutor.execute(markerBlockingJob); markerBlockingJob.waitUntilEnded(); Assert.assertTrue(markerBlockingJob.isEnded()); } finally { TestUtil.closePool(threadPoolExecutor); } } @Test public void testExecuteWithFullTaskQueue() { RecordRejectedExecutionHandler recordRejectedExecutionHandler = new RecordRejectedExecutionHandler(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1, recordRejectedExecutionHandler, Executors.defaultThreadFactory(), new ThreadPoolHandlerAdapter()); try { List<Runnable> rejectedList = recordRejectedExecutionHandler.getRejectedList(); threadPoolExecutor.execute(new MarkerBlockingJob(true)); Assert.assertEquals( rejectedList.toString(), 0, rejectedList.size()); threadPoolExecutor.execute(new MarkerBlockingJob(true)); Assert.assertEquals( rejectedList.toString(), 0, rejectedList.size()); MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob(); threadPoolExecutor.execute(markerBlockingJob); Assert.assertEquals( rejectedList.toString(), 1, rejectedList.size()); Assert.assertSame(markerBlockingJob, rejectedList.get(0)); Assert.assertFalse(markerBlockingJob.isStarted()); } finally { TestUtil.closePool(threadPoolExecutor, true); } } @Test public void testExecuteWorkerThreadDead() throws InterruptedException { SetRecordUncaughtExceptionThreadFactory threadFactory = new SetRecordUncaughtExceptionThreadFactory(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 10, new AbortPolicy(), threadFactory, new ThreadPoolHandlerAdapter()); RecordUncaughtExceptionHandler recordUncaughtExceptionHandler = threadFactory.getRecordUncaughtExceptionHandler(); Queue<MarkerBlockingJob> markerBlockingJobQueue = new LinkedList<>(); try { for (int i = 0; i < 10; i++) { MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob( false, true); markerBlockingJobQueue.add(markerBlockingJob); threadPoolExecutor.execute(markerBlockingJob); } } finally { TestUtil.closePool(threadPoolExecutor); for (Thread thread : threadFactory.getCreatedThreads()) { thread.join(); } } Assert.assertEquals(1, threadPoolExecutor.getLargestPoolSize()); Assert.assertEquals( 10, recordUncaughtExceptionHandler.getUncaughtMap().size()); for (MarkerBlockingJob markerBlockingJob : markerBlockingJobQueue) { Assert.assertTrue(markerBlockingJob.isStarted()); Assert.assertFalse(markerBlockingJob.isEnded()); } } @Test public void testFinalize() { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 2, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 3); Assert.assertFalse(threadPoolExecutor.isShutdown()); threadPoolExecutor.finalize(); Assert.assertTrue(threadPoolExecutor.isShutdown()); } @Test public void testShutdownNowAfterTaskPolledBeforeTaskRunning() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, false, 1); MarkerBlockingJob markerBlockingJob1 = new MarkerBlockingJob(true); MarkerBlockingJob markerBlockingJob2 = new MarkerBlockingJob(true); threadPoolExecutor.execute(markerBlockingJob1); markerBlockingJob1.waitUntilBlock(); threadPoolExecutor.execute(markerBlockingJob2); TaskQueue<Runnable> taskQueue = threadPoolExecutor.getTaskQueue(); AbstractQueuedSynchronizer headWorkerTask = null; ReentrantLock takeLock = taskQueue.getTakeLock(); takeLock.lock(); try { markerBlockingJob1.unBlock(); while (!takeLock.hasQueuedThreads()) { Thread.sleep(1); } Set<? extends AbstractQueuedSynchronizer> workerTasks = threadPoolExecutor.getWorkerTasks(); Assert.assertEquals(workerTasks.toString(), 1, workerTasks.size()); headWorkerTask = workerTasks.iterator().next(); headWorkerTask.acquire(1); } finally { takeLock.unlock(); } while (!headWorkerTask.hasQueuedThreads()) { Thread.sleep(1); } threadPoolExecutor.shutdownNow(); headWorkerTask.release(1); Assert.assertTrue( threadPoolExecutor.awaitTermination(1, TimeUnit.SECONDS)); Assert.assertTrue(markerBlockingJob2.isInterrupted()); } @Test public void testShutdownNowAfterTaskQueuePollingTimeoutBeforeExitChecking() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1); MarkerBlockingJob markerBlockingJob = new MarkerBlockingJob(true); threadPoolExecutor.execute(markerBlockingJob); markerBlockingJob.waitUntilBlock(); ReentrantLock mainLock = threadPoolExecutor.getMainLock(); TaskQueue<Runnable> taskQueue = threadPoolExecutor.getTaskQueue(); ReentrantLock takeLock = taskQueue.getTakeLock(); takeLock.lock(); try { markerBlockingJob.unBlock(); while (!takeLock.hasQueuedThreads()) { Thread.sleep(1); } mainLock.lock(); } finally { takeLock.unlock(); } try { while (!mainLock.hasQueuedThreads()) { Thread.sleep(1); } threadPoolExecutor.shutdownNow(); } finally { mainLock.unlock(); } Assert.assertTrue(threadPoolExecutor.isShutdown()); Assert.assertTrue( threadPoolExecutor.awaitTermination(1, TimeUnit.SECONDS)); } @Test public void testTerminationNoticeableFuture() throws InterruptedException { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 1, TestUtil.KEEPALIVE_TIME, TimeUnit.MILLISECONDS, true, 1); NoticeableFuture<Void> terminationNoticeableFutute = threadPoolExecutor.terminationNoticeableFuture(); Assert.assertFalse(terminationNoticeableFutute.isDone()); Assert.assertFalse(terminationNoticeableFutute.cancel(true)); final AtomicBoolean marker = new AtomicBoolean(); terminationNoticeableFutute.addFutureListener( new FutureListener<Void>() { @Override public void complete(Future<Void> future) { marker.set(true); } }); threadPoolExecutor.shutdown(); Assert.assertTrue( threadPoolExecutor.awaitTermination(1, TimeUnit.SECONDS)); Assert.assertTrue(terminationNoticeableFutute.isDone()); Assert.assertTrue(marker.get()); } }