public static DynamicThreadPoolExecutor buildDynamicPool(ThreadPoolInitParam initParam) {
        Assert.notNull(initParam);
        DynamicThreadPoolExecutor dynamicThreadPoolExecutor;
        try {
            dynamicThreadPoolExecutor = new DynamicThreadPoolExecutor(
                    initParam.getCorePoolNum(),
                    initParam.getMaximumPoolSize(),
                    initParam.getKeepAliveTime(),
                    initParam.getTimeUnit(),
                    initParam.getExecuteTimeOut(),
                    initParam.getWaitForTasksToCompleteOnShutdown(),
                    initParam.getAwaitTerminationMillis(),
                    initParam.getWorkQueue(),
                    initParam.getThreadPoolId(),
                    initParam.getThreadFactory(),
                    initParam.getRejectedExecutionHandler());
        } catch (IllegalArgumentException ex) {
            throw new IllegalArgumentException(String.format("Error creating thread pool parameter. threadPool id: %s", initParam.getThreadPoolId()), ex);
        }
        dynamicThreadPoolExecutor.setTaskDecorator(initParam.getTaskDecorator());
        dynamicThreadPoolExecutor.allowCoreThreadTimeOut(initParam.allowCoreThreadTimeOut);
        return dynamicThreadPoolExecutor;
    }
@Test
    public void testBuildDynamicPool() {
        initParam.setWaitForTasksToCompleteOnShutdown(true);
        initParam.setAwaitTerminationMillis(5000L);
        ThreadPoolExecutor executor = AbstractBuildThreadPoolTemplate.buildDynamicPool(initParam);
        AtomicInteger count = new AtomicInteger(0);
        executor.submit(() -> {
            ThreadUtil.sleep(100L);
            return count.incrementAndGet();
        });
        executor.submit(() -> {
            ThreadUtil.sleep(100L);
            count.incrementAndGet();
        });
        // waiting for shutdown
        executor.shutdown();
        while (!executor.isTerminated()) {
        }

        Assert.assertEquals(2, count.get());
    }