Use of SpringBoot global thread pool and local thread pool

 

catalogue

Thread pool

Global thread pool

Local thread pool

Thread pool

        Thread pool is to create some threads first, and their collection is called thread pool. Using thread pool can improve performance. When the system starts, the thread pool creates a large number of idle threads. The program passes a task to the thread pool, and the thread pool will start a thread to execute the task. After execution, the thread will not die, but return to the thread pool to become idle again and wait for the execution of the next task.

Global thread pool

For spring boot, it is very convenient to configure the global thread pool. Add the configuration to initialize a thread pool

@Configuration
@EnableAsync
public class ExecutorConfig {
 
    @Bean("new_Thread")
    public Executor carSocketExecutor() {
        //Gets the number of cores for the current machine
        int cpuNum = Runtime.getRuntime().availableProcessors();
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //Configure the number of core threads
        executor.setCorePoolSize(cpuNum);
        //Configure maximum threads
        executor.setMaxPoolSize(cpuNum * 2);
        //Configure queue size
        executor.setQueueCapacity(100);
        //Thread lifetime
        executor.setKeepAliveSeconds(60);
        //Configure the name prefix of threads in the thread pool
        executor.setThreadNamePrefix("new_Thread");
        // CALLER_RUNS: the task is not executed in the new thread, but in the thread of the caller
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //Perform initialization
        executor.initialize();
        return executor;
}
 

If the returned value is tested here, the return value type is Future. The @ Async annotation indicates that the method obtains threads from the thread pool for execution, and the thread pool name is not required

@Override
    @Async("new_Thread")
    public Future<String> testService01() {
        try {
            System.out.println("Thread name " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<String>("test01 Execution complete!");
    }

    @Override
    @Async("new_Thread")
    public Future<String> testService02() {
        try {
            System.out.println("Thread name " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<String>("test02 Execution complete!");
    }

    @Override
    @Async("new_Thread")
    public Future<String> testService03() {
        try {
            System.out.println("Thread name " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<String>("test03 Execution complete!");
    }

  Test methods. Because of multithreading, the main thread will not wait for the return value of each method, so first put the return value results into a collection until all methods start to execute, and then traverse them. The get () method in Future can get the real return value. Only when this method is called, The main thread will wait for the result in the method to return

@GetMapping("/test01")
    public StringBuilder test01() {

        //Return result set
        List<Future<String>> results = new ArrayList<>();

        //Response results
        StringBuilder restStr = new StringBuilder();

        //start time
        Long startTime = System.currentTimeMillis();

        results.add(multithreadingService.testService01());
        results.add(multithreadingService.testService02());
        results.add(multithreadingService.testService03());

        for (Future<String> result : results) {
            try {
                restStr.append(result.get()).append("\n");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        //End time
        Long endTime = System.currentTimeMillis();

        restStr.append("Shared time").append(endTime - startTime).append("ms");
        return restStr;
    }

Looking at the test results, we can see that the three methods share about 10s. At the beginning, I set the execution time of each method to 10s, so   The test was successful!

 

 

Local thread pool

Creating a local thread pool can be implemented using the methods in the Executors class. This article demonstrates the creation of a fixed length thread pool

The test method is the same as the previous global thread pool

@Override
    public String testService04() {
        try {
            System.out.println("Thread name " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "test04 Execution complete!";
    }

    @Override
    public String testService05() {
        try {
            System.out.println("Thread name " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "test05 Execution complete!";
    }

    @Override
    public String testService06() {
        try {
            System.out.println("Thread name " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "test06 Execution complete!";
    }
@GetMapping("/test02")
    public StringBuilder test02() {
        //Return result set
        List<Future<String>> results = new ArrayList<>();

        //Response results
        StringBuilder restStr = new StringBuilder();

        //start time
        Long startTime = System.currentTimeMillis();

        //Create a fixed length thread pool (indicating that the maximum concurrency is 3, and wait if the queue exceeds 3)
        ExecutorService executorService = Executors.newFixedThreadPool(POOL_COUNT, new MyThreadFactory("my_thread"));

        results.add(executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.interrupted();
                return multithreadingService.testService04();
            }
        }));

        results.add(executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.interrupted();
                return multithreadingService.testService05();
            }
        }));

        results.add(executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.interrupted();
                return multithreadingService.testService06();
            }
        }));

        for (Future<String> result : results) {
            try {
                restStr.append(result.get()).append("\n");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //Close thread pool
                executorService.shutdown();
            }
        }

        //End time
        Long endTime = System.currentTimeMillis();

        restStr.append("Shared time").append(endTime - startTime).append("ms");
        return restStr;
    }

  The thread factory here mainly gives a name to the thread. In addition, some log information such as thread creation time and end time can be added according to business requirements

@Data
public class MyThreadFactory implements ThreadFactory {
    //Thread name
    private String poolName;
    //Thread number
    private int threadCount;

    public MyThreadFactory(String poolName) {
        this.poolName = poolName;
        threadCount = 0;
    }

    @Override
    public Thread newThread(Runnable runnable) {
        threadCount++;
        return new Thread(runnable, poolName + "_" +threadCount);
    }

test result

 

 

Keywords: Java Spring Spring Boot thread pool

Added by FangerZero on Tue, 23 Nov 2021 04:49:34 +0200