目录

线程池

全局线程池

局部线程池


线程池

        线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。

全局线程池

对于SpringBoot来说,配置全局线程池还是非常方便的,加入一下配置初始化一个线程池

@Configuration
@EnableAsync
public class ExecutorConfig {
 
    @Bean("new_Thread")
    public Executor carSocketExecutor() {
        //获取当前机器的核数
        int cpuNum = Runtime.getRuntime().availableProcessors();
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(cpuNum);
        //配置最大线程数
        executor.setMaxPoolSize(cpuNum * 2);
        //配置队列大小
        executor.setQueueCapacity(100);
        //线程存活时间
        executor.setKeepAliveSeconds(60);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("new_Thread");
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
}
 

这里测试的实在其有返回值的情况下,返回值类型为Future,@Async注解表示该方法从线程池中获取线程来执行,其中线程池名称为非必填

@Override
    @Async("new_Thread")
    public Future<String> testService01() {
        try {
            System.out.println("线程名称 " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<String>("test01执行完毕!");
    }

    @Override
    @Async("new_Thread")
    public Future<String> testService02() {
        try {
            System.out.println("线程名称 " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<String>("test02执行完毕!");
    }

    @Override
    @Async("new_Thread")
    public Future<String> testService03() {
        try {
            System.out.println("线程名称 " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<String>("test03执行完毕!");
    }

 测试方法,因为是多线程的原因,主线程不会等待每一个方法的返回值,所以先将返回值结果统一放进一个集合中,直到所有方法都开始执行后在对其进行遍历,Future中的get()方法可以获取到真正的返回值,只有调用了这个方法,主线程才会等待方法中的结果返回

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

        //返回结果集
        List<Future<String>> results = new ArrayList<>();

        //响应结果
        StringBuilder restStr = new StringBuilder();

        //开始时间
        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();
            }
        }

        //结束时间
        Long endTime = System.currentTimeMillis();

        restStr.append("共用时").append(endTime - startTime).append("ms");
        return restStr;
    }

查看测试结果,可以看到三个方法共用时大约10s钟,开头我给每个方法的执行时间都设置的10s,所以 此次测试是成功的!

 

 

局部线程池

创建局部线程池可以使用Executors类中的方法来实现,本文中演示创建为一个固定长度的线程池

测试方法跟前面的全局线程池一样

@Override
    public String testService04() {
        try {
            System.out.println("线程名称 " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "test04执行完毕!";
    }

    @Override
    public String testService05() {
        try {
            System.out.println("线程名称 " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "test05执行完毕!";
    }

    @Override
    public String testService06() {
        try {
            System.out.println("线程名称 " + Thread.currentThread().getName());
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "test06执行完毕!";
    }
@GetMapping("/test02")
    public StringBuilder test02() {
        //返回结果集
        List<Future<String>> results = new ArrayList<>();

        //响应结果
        StringBuilder restStr = new StringBuilder();

        //开始时间
        Long startTime = System.currentTimeMillis();

        //创建一个固定长度的线程池(表示最大并发量为3,队列超过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 {
                //关闭线程池
                executorService.shutdown();
            }
        }

        //结束时间
        Long endTime = System.currentTimeMillis();

        restStr.append("共用时").append(endTime - startTime).append("ms");
        return restStr;
    }

 线程工厂这里主要是给线程起一个名字,另外还可以根据业务需求加入一些线程的创建时间,结束时间等日志信息在其中

@Data
public class MyThreadFactory implements ThreadFactory {
    //线程名称
    private String poolName;
    //线程编号
    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);
    }

测试结果

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐