PageRenderTime 27ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/core/petra/petra-concurrent/src/test/java/com/liferay/petra/concurrent/NoticeableThreadPoolExecutorTest.java

http://github.com/liferay/liferay-portal
Java | 756 lines | 553 code | 187 blank | 16 comment | 11 complexity | f5b41e71e90b638d895c35165928eb77 MD5 | raw file
Possible License(s): LGPL-2.0
  1. /**
  2. * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or modify it under
  5. * the terms of the GNU Lesser General Public License as published by the Free
  6. * Software Foundation; either version 2.1 of the License, or (at your option)
  7. * any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  12. * details.
  13. */
  14. package com.liferay.petra.concurrent;
  15. import com.liferay.petra.reflect.ReflectionUtil;
  16. import com.liferay.petra.test.util.ThreadTestUtil;
  17. import com.liferay.portal.kernel.test.ReflectionTestUtil;
  18. import com.liferay.portal.kernel.test.rule.AggregateTestRule;
  19. import com.liferay.portal.kernel.test.rule.CodeCoverageAssertor;
  20. import com.liferay.portal.test.rule.LiferayUnitTestRule;
  21. import java.util.List;
  22. import java.util.concurrent.BlockingQueue;
  23. import java.util.concurrent.Callable;
  24. import java.util.concurrent.Future;
  25. import java.util.concurrent.LinkedBlockingQueue;
  26. import java.util.concurrent.Semaphore;
  27. import java.util.concurrent.SynchronousQueue;
  28. import java.util.concurrent.ThreadFactory;
  29. import java.util.concurrent.ThreadPoolExecutor;
  30. import java.util.concurrent.TimeUnit;
  31. import java.util.concurrent.atomic.AtomicBoolean;
  32. import java.util.concurrent.atomic.AtomicInteger;
  33. import org.junit.Assert;
  34. import org.junit.ClassRule;
  35. import org.junit.Rule;
  36. import org.junit.Test;
  37. /**
  38. * @author Shuyang Zhou
  39. */
  40. public class NoticeableThreadPoolExecutorTest {
  41. @ClassRule
  42. @Rule
  43. public static final AggregateTestRule aggregateTestRule =
  44. new AggregateTestRule(
  45. new CodeCoverageAssertor() {
  46. @Override
  47. public void appendAssertClasses(List<Class<?>> assertClasses) {
  48. assertClasses.add(BaseNoticeableExecutorService.class);
  49. }
  50. },
  51. LiferayUnitTestRule.INSTANCE);
  52. @Test
  53. public void testAdjustSize() throws InterruptedException {
  54. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  55. new NoticeableThreadPoolExecutor(
  56. 1, 1, 1, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(),
  57. new MethodNameThreadFactory(),
  58. (runnable, threadPoolExecutor) -> {
  59. },
  60. new ThreadPoolHandlerAdapter());
  61. Assert.assertEquals(1, noticeableThreadPoolExecutor.getCorePoolSize());
  62. Assert.assertEquals(
  63. 1, noticeableThreadPoolExecutor.getMaximumPoolSize());
  64. try {
  65. noticeableThreadPoolExecutor.setCorePoolSize(0);
  66. Assert.fail();
  67. }
  68. catch (IllegalArgumentException illegalArgumentException) {
  69. Assert.assertEquals(
  70. "To ensure FIFO, core pool size must be 1 or greater",
  71. illegalArgumentException.getMessage());
  72. }
  73. noticeableThreadPoolExecutor.setCorePoolSize(2);
  74. Assert.assertEquals(2, noticeableThreadPoolExecutor.getCorePoolSize());
  75. noticeableThreadPoolExecutor.setMaximumPoolSize(3);
  76. Assert.assertEquals(
  77. 3, noticeableThreadPoolExecutor.getMaximumPoolSize());
  78. noticeableThreadPoolExecutor.shutdown();
  79. Assert.assertTrue(
  80. noticeableThreadPoolExecutor.awaitTermination(
  81. 10, TimeUnit.MINUTES));
  82. }
  83. @Test
  84. public void testAwaitTermination() throws InterruptedException {
  85. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  86. new NoticeableThreadPoolExecutor(
  87. 1, 1, 1, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(),
  88. new MethodNameThreadFactory(),
  89. (runnable, threadPoolExecutor) -> {
  90. },
  91. new ThreadPoolHandlerAdapter());
  92. Assert.assertFalse(
  93. noticeableThreadPoolExecutor.awaitTermination(
  94. 1, TimeUnit.NANOSECONDS));
  95. ThreadPoolExecutor dispatcherThreadPoolExecutor =
  96. ReflectionTestUtil.getFieldValue(
  97. noticeableThreadPoolExecutor, "_dispatcherThreadPoolExecutor");
  98. dispatcherThreadPoolExecutor.shutdown();
  99. Assert.assertFalse(
  100. noticeableThreadPoolExecutor.awaitTermination(
  101. 1, TimeUnit.NANOSECONDS));
  102. noticeableThreadPoolExecutor.shutdown();
  103. Assert.assertTrue(
  104. noticeableThreadPoolExecutor.awaitTermination(
  105. 10, TimeUnit.MINUTES));
  106. }
  107. @Test
  108. public void testConstructor() {
  109. try {
  110. new NoticeableThreadPoolExecutor(
  111. 0, 1, 1, TimeUnit.NANOSECONDS, new SynchronousQueue<>(),
  112. new MethodNameThreadFactory(),
  113. (runnable, threadPoolExecutor) -> {
  114. },
  115. new ThreadPoolHandlerAdapter());
  116. Assert.fail();
  117. }
  118. catch (IllegalArgumentException illegalArgumentException) {
  119. Assert.assertEquals(
  120. "To ensure FIFO, core pool size must be 1 or greater",
  121. illegalArgumentException.getMessage());
  122. }
  123. new NoticeableThreadPoolExecutor(
  124. 1, 1, 1, TimeUnit.NANOSECONDS, new SynchronousQueue<>(),
  125. new MethodNameThreadFactory(),
  126. (runnable, threadPoolExecutor) -> {
  127. },
  128. new ThreadPoolHandlerAdapter());
  129. }
  130. @Test
  131. public void testMisc() throws InterruptedException {
  132. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  133. new NoticeableThreadPoolExecutor(
  134. 1, 1, 1, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(),
  135. new MethodNameThreadFactory(),
  136. (runnable, threadPoolExecutor) -> {
  137. },
  138. new ThreadPoolHandlerAdapter());
  139. try {
  140. noticeableThreadPoolExecutor.execute(null);
  141. Assert.fail();
  142. }
  143. catch (NullPointerException nullPointerException) {
  144. }
  145. Assert.assertFalse(noticeableThreadPoolExecutor.isShutdown());
  146. Assert.assertFalse(noticeableThreadPoolExecutor.isTerminated());
  147. ThreadPoolExecutor workerThreadPoolExecutor =
  148. ReflectionTestUtil.getFieldValue(
  149. noticeableThreadPoolExecutor, "_workerThreadPoolExecutor");
  150. workerThreadPoolExecutor.shutdown();
  151. Assert.assertTrue(
  152. workerThreadPoolExecutor.awaitTermination(10, TimeUnit.MINUTES));
  153. Assert.assertTrue(noticeableThreadPoolExecutor.isTerminated());
  154. noticeableThreadPoolExecutor.shutdown();
  155. Assert.assertTrue(noticeableThreadPoolExecutor.isShutdown());
  156. Assert.assertTrue(
  157. noticeableThreadPoolExecutor.awaitTermination(
  158. 10, TimeUnit.MINUTES));
  159. Assert.assertTrue(noticeableThreadPoolExecutor.isTerminated());
  160. }
  161. @Test
  162. public void testRejectedByFullQueueAndExecuted()
  163. throws InterruptedException {
  164. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  165. new NoticeableThreadPoolExecutor(
  166. 1, 1, 1, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(),
  167. new MethodNameThreadFactory(),
  168. (runnable, threadPoolExecutor) -> {
  169. },
  170. new ThreadPoolHandlerAdapter());
  171. Semaphore semaphore = new Semaphore(0);
  172. Runnable slowRunnable = () -> {
  173. try {
  174. semaphore.acquire();
  175. }
  176. catch (InterruptedException interruptedException) {
  177. ReflectionUtil.throwException(interruptedException);
  178. }
  179. };
  180. noticeableThreadPoolExecutor.execute(slowRunnable);
  181. noticeableThreadPoolExecutor.execute(slowRunnable);
  182. BlockingQueue<Runnable> workerTaskQueue = _getWorkerTaskQueue(
  183. noticeableThreadPoolExecutor);
  184. Assert.assertSame(slowRunnable, workerTaskQueue.take());
  185. semaphore.release();
  186. workerTaskQueue.put(slowRunnable);
  187. semaphore.release();
  188. noticeableThreadPoolExecutor.shutdown();
  189. Assert.assertTrue(
  190. noticeableThreadPoolExecutor.awaitTermination(
  191. 10, TimeUnit.MINUTES));
  192. }
  193. @Test
  194. public void testRejectedByFullQueueAndInterruptted()
  195. throws InterruptedException {
  196. BlockingQueue<Runnable> dispatchTaskQueue = new LinkedBlockingQueue<>();
  197. BlockingQueue<Runnable> rejectedTaskQueue = new LinkedBlockingQueue<>();
  198. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  199. new NoticeableThreadPoolExecutor(
  200. 1, 1, 1, TimeUnit.NANOSECONDS, dispatchTaskQueue,
  201. new MethodNameThreadFactory(),
  202. (runnable, threadPoolExecutor) -> rejectedTaskQueue.add(
  203. runnable),
  204. new ThreadPoolHandlerAdapter());
  205. Semaphore semaphore = new Semaphore(0);
  206. Runnable slowRunnable = () -> {
  207. try {
  208. semaphore.acquire();
  209. }
  210. catch (InterruptedException interruptedException) {
  211. ReflectionUtil.throwException(interruptedException);
  212. }
  213. };
  214. noticeableThreadPoolExecutor.execute(slowRunnable);
  215. noticeableThreadPoolExecutor.execute(slowRunnable);
  216. while (!dispatchTaskQueue.isEmpty());
  217. ThreadPoolExecutor dispatcherThreadPoolExecutor =
  218. ReflectionTestUtil.getFieldValue(
  219. noticeableThreadPoolExecutor, "_dispatcherThreadPoolExecutor");
  220. dispatcherThreadPoolExecutor.shutdownNow();
  221. Assert.assertSame(slowRunnable, rejectedTaskQueue.take());
  222. semaphore.release();
  223. noticeableThreadPoolExecutor.shutdown();
  224. Assert.assertTrue(
  225. noticeableThreadPoolExecutor.awaitTermination(
  226. 10, TimeUnit.MINUTES));
  227. }
  228. @Test
  229. public void testRejectedByShutdownNoticeableThreadPoolExecutor()
  230. throws InterruptedException {
  231. BlockingQueue<Runnable> rejectedTasks = new LinkedBlockingQueue<>();
  232. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  233. new NoticeableThreadPoolExecutor(
  234. 1, 1, 1, TimeUnit.NANOSECONDS, new SynchronousQueue<>(),
  235. new MethodNameThreadFactory(),
  236. (runnable, threadPoolExecutor) -> rejectedTasks.add(runnable),
  237. new ThreadPoolHandlerAdapter());
  238. noticeableThreadPoolExecutor.shutdown();
  239. Runnable runnable = () -> {
  240. };
  241. noticeableThreadPoolExecutor.execute(runnable);
  242. Assert.assertSame(runnable, rejectedTasks.take());
  243. }
  244. @Test
  245. public void testRejectedByShutdownWorkerThreadPoolExecutor()
  246. throws InterruptedException {
  247. BlockingQueue<Runnable> rejectedTasks = new LinkedBlockingQueue<>();
  248. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  249. new NoticeableThreadPoolExecutor(
  250. 1, 1, 1, TimeUnit.NANOSECONDS, new SynchronousQueue<>(),
  251. new MethodNameThreadFactory(),
  252. (runnable, threadPoolExecutor) -> rejectedTasks.add(runnable),
  253. new ThreadPoolHandlerAdapter());
  254. ThreadPoolExecutor workerThreadPoolExecutor =
  255. ReflectionTestUtil.getFieldValue(
  256. noticeableThreadPoolExecutor, "_workerThreadPoolExecutor");
  257. workerThreadPoolExecutor.shutdown();
  258. Runnable runnable = () -> {
  259. };
  260. noticeableThreadPoolExecutor.execute(runnable);
  261. Assert.assertSame(runnable, rejectedTasks.take());
  262. }
  263. @Test
  264. public void testShutdownBeforeShutdowNow() throws InterruptedException {
  265. _testShutdownNow(true);
  266. }
  267. @Test
  268. public void testShutdownNow() throws InterruptedException {
  269. _testShutdownNow(false);
  270. }
  271. @Test
  272. public void testStatisticMethods() throws InterruptedException {
  273. BlockingQueue<Runnable> taskBlockingQueue = new LinkedBlockingQueue<>();
  274. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  275. new NoticeableThreadPoolExecutor(
  276. 1, 2, 1, TimeUnit.NANOSECONDS, taskBlockingQueue,
  277. new MethodNameThreadFactory(),
  278. (runnable, threadPoolExecutor) -> {
  279. },
  280. new ThreadPoolHandlerAdapter());
  281. Assert.assertEquals(0, noticeableThreadPoolExecutor.getActiveCount());
  282. Assert.assertEquals(
  283. 0, noticeableThreadPoolExecutor.getCompletedTaskCount());
  284. Assert.assertEquals(1, noticeableThreadPoolExecutor.getCorePoolSize());
  285. Assert.assertEquals(
  286. 0, noticeableThreadPoolExecutor.getLargestPoolSize());
  287. Assert.assertEquals(
  288. 2, noticeableThreadPoolExecutor.getMaximumPoolSize());
  289. Assert.assertEquals(
  290. 0, noticeableThreadPoolExecutor.getPendingTaskCount());
  291. Assert.assertEquals(0, noticeableThreadPoolExecutor.getPoolSize());
  292. BlockingQueue<Object> runningBlockingTaskQueue =
  293. new LinkedBlockingQueue<>();
  294. Semaphore semaphore = new Semaphore(0);
  295. Runnable slowRunnable = () -> {
  296. runningBlockingTaskQueue.add(this);
  297. try {
  298. semaphore.acquire();
  299. }
  300. catch (InterruptedException interruptedException) {
  301. ReflectionUtil.throwException(interruptedException);
  302. }
  303. };
  304. noticeableThreadPoolExecutor.execute(slowRunnable);
  305. runningBlockingTaskQueue.take();
  306. Assert.assertEquals(1, noticeableThreadPoolExecutor.getActiveCount());
  307. Assert.assertEquals(
  308. 0, noticeableThreadPoolExecutor.getCompletedTaskCount());
  309. Assert.assertEquals(1, noticeableThreadPoolExecutor.getCorePoolSize());
  310. Assert.assertEquals(
  311. 1, noticeableThreadPoolExecutor.getLargestPoolSize());
  312. Assert.assertEquals(
  313. 2, noticeableThreadPoolExecutor.getMaximumPoolSize());
  314. Assert.assertEquals(
  315. 0, noticeableThreadPoolExecutor.getPendingTaskCount());
  316. Assert.assertEquals(1, noticeableThreadPoolExecutor.getPoolSize());
  317. noticeableThreadPoolExecutor.execute(slowRunnable);
  318. runningBlockingTaskQueue.take();
  319. Assert.assertEquals(2, noticeableThreadPoolExecutor.getActiveCount());
  320. Assert.assertEquals(
  321. 0, noticeableThreadPoolExecutor.getCompletedTaskCount());
  322. Assert.assertEquals(1, noticeableThreadPoolExecutor.getCorePoolSize());
  323. Assert.assertEquals(
  324. 2, noticeableThreadPoolExecutor.getLargestPoolSize());
  325. Assert.assertEquals(
  326. 2, noticeableThreadPoolExecutor.getMaximumPoolSize());
  327. Assert.assertEquals(
  328. 0, noticeableThreadPoolExecutor.getPendingTaskCount());
  329. Assert.assertEquals(2, noticeableThreadPoolExecutor.getPoolSize());
  330. noticeableThreadPoolExecutor.execute(slowRunnable);
  331. Thread dispatcherThread = null;
  332. for (Thread thread : ThreadTestUtil.getThreads()) {
  333. if (thread == null) {
  334. continue;
  335. }
  336. String name = thread.getName();
  337. if (name.startsWith("testStatisticMethods-") &&
  338. name.endsWith("-dispatcher")) {
  339. dispatcherThread = thread;
  340. break;
  341. }
  342. }
  343. Assert.assertNotNull(
  344. "Dispatcher thread is not started", dispatcherThread);
  345. while (dispatcherThread.getState() != Thread.State.WAITING);
  346. while (!taskBlockingQueue.isEmpty());
  347. Assert.assertEquals(2, noticeableThreadPoolExecutor.getActiveCount());
  348. Assert.assertEquals(
  349. 0, noticeableThreadPoolExecutor.getCompletedTaskCount());
  350. Assert.assertEquals(1, noticeableThreadPoolExecutor.getCorePoolSize());
  351. Assert.assertEquals(
  352. 2, noticeableThreadPoolExecutor.getLargestPoolSize());
  353. Assert.assertEquals(
  354. 2, noticeableThreadPoolExecutor.getMaximumPoolSize());
  355. Assert.assertEquals(
  356. 0, noticeableThreadPoolExecutor.getPendingTaskCount());
  357. Assert.assertEquals(2, noticeableThreadPoolExecutor.getPoolSize());
  358. noticeableThreadPoolExecutor.execute(slowRunnable);
  359. Assert.assertEquals(2, noticeableThreadPoolExecutor.getActiveCount());
  360. Assert.assertEquals(
  361. 0, noticeableThreadPoolExecutor.getCompletedTaskCount());
  362. Assert.assertEquals(1, noticeableThreadPoolExecutor.getCorePoolSize());
  363. Assert.assertEquals(
  364. 2, noticeableThreadPoolExecutor.getLargestPoolSize());
  365. Assert.assertEquals(
  366. 2, noticeableThreadPoolExecutor.getMaximumPoolSize());
  367. Assert.assertEquals(
  368. 1, noticeableThreadPoolExecutor.getPendingTaskCount());
  369. Assert.assertEquals(2, noticeableThreadPoolExecutor.getPoolSize());
  370. semaphore.release();
  371. runningBlockingTaskQueue.take();
  372. while (!taskBlockingQueue.isEmpty());
  373. Assert.assertEquals(2, noticeableThreadPoolExecutor.getActiveCount());
  374. Assert.assertEquals(
  375. 1, noticeableThreadPoolExecutor.getCompletedTaskCount());
  376. Assert.assertEquals(1, noticeableThreadPoolExecutor.getCorePoolSize());
  377. Assert.assertEquals(
  378. 2, noticeableThreadPoolExecutor.getLargestPoolSize());
  379. Assert.assertEquals(
  380. 2, noticeableThreadPoolExecutor.getMaximumPoolSize());
  381. Assert.assertEquals(
  382. 0, noticeableThreadPoolExecutor.getPendingTaskCount());
  383. Assert.assertEquals(2, noticeableThreadPoolExecutor.getPoolSize());
  384. semaphore.release();
  385. runningBlockingTaskQueue.take();
  386. semaphore.release();
  387. semaphore.release();
  388. noticeableThreadPoolExecutor.shutdown();
  389. Assert.assertTrue(
  390. noticeableThreadPoolExecutor.awaitTermination(
  391. 10, TimeUnit.MINUTES));
  392. Assert.assertEquals(0, noticeableThreadPoolExecutor.getActiveCount());
  393. Assert.assertEquals(
  394. 4, noticeableThreadPoolExecutor.getCompletedTaskCount());
  395. Assert.assertEquals(1, noticeableThreadPoolExecutor.getCorePoolSize());
  396. Assert.assertEquals(
  397. 2, noticeableThreadPoolExecutor.getLargestPoolSize());
  398. Assert.assertEquals(
  399. 2, noticeableThreadPoolExecutor.getMaximumPoolSize());
  400. Assert.assertEquals(
  401. 0, noticeableThreadPoolExecutor.getPendingTaskCount());
  402. Assert.assertEquals(0, noticeableThreadPoolExecutor.getPoolSize());
  403. }
  404. @Test
  405. public void testSubmit() throws Exception {
  406. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  407. new NoticeableThreadPoolExecutor(
  408. 1, 1, 1, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(),
  409. new MethodNameThreadFactory(),
  410. (runnable, threadPoolExecutor) -> {
  411. },
  412. new ThreadPoolHandlerAdapter());
  413. try {
  414. noticeableThreadPoolExecutor.submit((Callable<?>)null);
  415. Assert.fail();
  416. }
  417. catch (NullPointerException nullPointerException) {
  418. Assert.assertEquals(
  419. "Callable is null", nullPointerException.getMessage());
  420. }
  421. NoticeableFuture<String> noticeableFuture1 =
  422. noticeableThreadPoolExecutor.submit(() -> "test");
  423. Assert.assertEquals("test", noticeableFuture1.get());
  424. AtomicBoolean flag = new AtomicBoolean();
  425. NoticeableFuture<?> noticeableFuture2 =
  426. noticeableThreadPoolExecutor.submit(() -> flag.set(true));
  427. Assert.assertNull(noticeableFuture2.get());
  428. Assert.assertTrue(flag.get());
  429. try {
  430. noticeableThreadPoolExecutor.submit(null, null);
  431. Assert.fail();
  432. }
  433. catch (NullPointerException nullPointerException) {
  434. Assert.assertEquals(
  435. "Runnable is null", nullPointerException.getMessage());
  436. }
  437. NoticeableFuture<String> noticeableFuture3 =
  438. noticeableThreadPoolExecutor.submit(() -> flag.set(false), "test");
  439. Assert.assertEquals("test", noticeableFuture3.get());
  440. Assert.assertFalse(flag.get());
  441. noticeableThreadPoolExecutor.shutdown();
  442. Assert.assertTrue(
  443. noticeableThreadPoolExecutor.awaitTermination(
  444. 10, TimeUnit.MINUTES));
  445. }
  446. @Test
  447. public void testTerminationNoticeableFuture() throws InterruptedException {
  448. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  449. new NoticeableThreadPoolExecutor(
  450. 1, 1, 1, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(),
  451. new MethodNameThreadFactory(),
  452. (runnable, threadPoolExecutor) -> {
  453. },
  454. new ThreadPoolHandlerAdapter());
  455. NoticeableFuture<Void> terminationNoticeableFuture =
  456. noticeableThreadPoolExecutor.terminationNoticeableFuture();
  457. Assert.assertFalse(terminationNoticeableFuture.isDone());
  458. AtomicBoolean terminated = new AtomicBoolean();
  459. terminationNoticeableFuture.addFutureListener(
  460. future -> terminated.set(true));
  461. noticeableThreadPoolExecutor.shutdown();
  462. Assert.assertTrue(
  463. noticeableThreadPoolExecutor.awaitTermination(
  464. 10, TimeUnit.MINUTES));
  465. Assert.assertTrue(terminated.get());
  466. }
  467. @Test
  468. public void testThreadPoolHandler() throws Exception {
  469. BlockingQueue<String> executionPaths = new LinkedBlockingQueue<>();
  470. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  471. new NoticeableThreadPoolExecutor(
  472. 1, 1, 1, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(),
  473. new MethodNameThreadFactory(),
  474. (runnable, threadPoolExecutor) -> {
  475. },
  476. new ThreadPoolHandler() {
  477. @Override
  478. public void afterExecute(
  479. Runnable runnable, Throwable throwable) {
  480. executionPaths.add("afterExecute");
  481. }
  482. @Override
  483. public void beforeExecute(
  484. Thread thread, Runnable runnable) {
  485. executionPaths.add("beforeExecute");
  486. }
  487. @Override
  488. public void terminated() {
  489. executionPaths.add("terminated");
  490. }
  491. });
  492. NoticeableFuture<Void> terminationNoticeableFuture =
  493. noticeableThreadPoolExecutor.terminationNoticeableFuture();
  494. terminationNoticeableFuture.addFutureListener(
  495. future -> executionPaths.add("terminationNoticeableFuture"));
  496. Future<?> future = noticeableThreadPoolExecutor.submit(
  497. () -> executionPaths.add("runnable"));
  498. future.get();
  499. noticeableThreadPoolExecutor.shutdown();
  500. Assert.assertTrue(
  501. noticeableThreadPoolExecutor.awaitTermination(
  502. 10, TimeUnit.MINUTES));
  503. Assert.assertEquals(
  504. executionPaths.toString(), 5, executionPaths.size());
  505. Assert.assertEquals("beforeExecute", executionPaths.take());
  506. Assert.assertEquals("runnable", executionPaths.take());
  507. Assert.assertEquals("afterExecute", executionPaths.take());
  508. Assert.assertEquals("terminated", executionPaths.take());
  509. Assert.assertEquals(
  510. "terminationNoticeableFuture", executionPaths.take());
  511. }
  512. private BlockingQueue<Runnable> _getWorkerTaskQueue(
  513. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor) {
  514. ThreadPoolExecutor workerThreadPoolExecutor =
  515. ReflectionTestUtil.getFieldValue(
  516. noticeableThreadPoolExecutor, "_workerThreadPoolExecutor");
  517. return workerThreadPoolExecutor.getQueue();
  518. }
  519. private void _testShutdownNow(boolean shutdownBeforeShutdownNow)
  520. throws InterruptedException {
  521. BlockingQueue<Runnable> taskBlockingQueue = new LinkedBlockingQueue<>();
  522. NoticeableThreadPoolExecutor noticeableThreadPoolExecutor =
  523. new NoticeableThreadPoolExecutor(
  524. 1, 1, 1, TimeUnit.NANOSECONDS, taskBlockingQueue,
  525. new MethodNameThreadFactory(),
  526. (runnable, threadPoolExecutor) -> {
  527. },
  528. new ThreadPoolHandlerAdapter());
  529. Semaphore semaphore = new Semaphore(0);
  530. Runnable slowRunnable = () -> {
  531. try {
  532. semaphore.acquire();
  533. }
  534. catch (InterruptedException interruptedException) {
  535. }
  536. };
  537. noticeableThreadPoolExecutor.execute(slowRunnable);
  538. noticeableThreadPoolExecutor.execute(slowRunnable);
  539. while (!taskBlockingQueue.isEmpty());
  540. noticeableThreadPoolExecutor.execute(slowRunnable);
  541. if (shutdownBeforeShutdownNow) {
  542. noticeableThreadPoolExecutor.shutdown();
  543. }
  544. List<Runnable> shutdownTasks =
  545. noticeableThreadPoolExecutor.shutdownNow();
  546. Assert.assertEquals(shutdownTasks.toString(), 1, shutdownTasks.size());
  547. shutdownTasks = noticeableThreadPoolExecutor.shutdownNow();
  548. Assert.assertTrue(shutdownTasks.toString(), shutdownTasks.isEmpty());
  549. Assert.assertTrue(
  550. noticeableThreadPoolExecutor.awaitTermination(
  551. 10, TimeUnit.MINUTES));
  552. }
  553. private static class MethodNameThreadFactory implements ThreadFactory {
  554. @Override
  555. public Thread newThread(Runnable runnable) {
  556. Thread thread = new Thread(
  557. runnable, _prefix + _counter.getAndIncrement());
  558. thread.setDaemon(true);
  559. return thread;
  560. }
  561. private MethodNameThreadFactory() {
  562. Exception exception = new Exception();
  563. StackTraceElement[] stackTraceElements = exception.getStackTrace();
  564. _prefix = stackTraceElements[2].getMethodName() + "-";
  565. }
  566. private final AtomicInteger _counter = new AtomicInteger();
  567. private final String _prefix;
  568. }
  569. }