多线程--线程池

本文介绍了线程池的概念,强调了其在提高线程利用率和响应时间上的优势。线程池可以通过ThreadPoolExecutor进行定制,包括核心线程数、最大线程数、等待队列等参数。示例代码展示了如何创建和使用线程池,并结合CountDownLatch优化接口响应时间。此外,文章还提及了Spring框架中线程池的集成应用。
摘要由CSDN通过智能技术生成

多线程–线程池

1、概念

进程:程序的基本实体,例如启动IDEA程序,是一个进程,电脑右击资源管理器中可查看目前电脑启动的进程;
线程:每一个进程中都可能多个线程在执行;

并发:单个CPU交替执行多个任务
并行:多个CPU同时执行多个任务
CPU核数是由硬件决定的,在程序执行中,线程数量远远大于CPU核数,高并发场景较为常见;

2、线程的创建方式

继承Thread类
实现Runnable接口
实现Callable和Future接口(区别:有返回值)

3、线程池概念及优势

池化思想:线程池,数据库连接池,字符串常量池
线程池可以预先创建多个线程,优点:

  • 提高线程利用率
  • 提高响应时间
  • 统一管理线程对象(可控制项目中最大线程数量);

可以将办理业务的方式看做线程池的模式:例如共有5个办理业务窗口,但目前只开设3个业务窗口,等待席位可容纳5人
若此时
小于3人办理业务:直接窗口办理;
若4人且前边3人均未办理完成,则第4人进入等待席位;
若等待席位满,再有人办理业务,则银行会开放剩余2个窗口办理业务
若5个窗口均开放且等待席位满,则告知客户去其它网点办理
若一段时间内剩余的2个窗口没有任务业务,则2个窗口关闭

在此情景中:
共有5个办理业务窗口:线程池的最大线程数;
当前只开放3个窗口,线程池核心线程数;
等待席位:等待队列(阻塞队列)
等待一段时间2个窗口关闭:线程存活时间

核心线程数和最大线程数设置

具体看业务场景:
线程数 = CPU * (1-线程等待时间/线程总执行时间)
线程数设置越多,会导致CPU切换频繁,
(个人理解)线程数可设置为CPU核数+1,若CPU使用率低,则可适当增大线程数

4、常见的创建线程池方式

创建线程池

public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3),Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        try{
            for(int i =0;i<9;i++){
                threadPoolExecutor.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"====办理业务;");
                });
            }
        }catch (Exception e){
            System.out.println(e.getMessage());
        }finally {
            threadPoolExecutor.shutdown();
        }
    }

不建议使用如下方式创建线程池,以下方式创建线程池阻塞队列没有限制,容易造成内存溢出
newFixedThreadPool
newCachedThreadPool
newSingleThreadExecutor
newScheduledThreadPool

5、实例应用

线程池结合countDownLatch 优化接口响应时间

public class Test {

//    public static void main(String[] args) throws InterruptedException {
//        LocalDateTime startTime = LocalDateTime.now();
//        int sum1 = sum(100000);
//        int sum2 = sum(100000);
//        int result = sum1+sum2;
//        System.out.println("最后结果为:"+result);
//        LocalDateTime endTime = LocalDateTime.now();
//        Duration time = Duration.between(startTime,endTime);
//        System.out.println("总耗时"+time.toMillis());
//    }
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService = new ThreadPoolExecutor(2, 2, 2L, TimeUnit.SECONDS,new ArrayBlockingQueue<>(3),Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        try{
            LocalDateTime start = LocalDateTime.now();
            final CountDownLatch countDownLatch = new CountDownLatch(2);
            Future<Integer> task1 = executorService.submit(() -> {
                return sum(10000);
            });
            countDownLatch.countDown();
            Future<Integer> task2 = executorService.submit(() -> {
                return sum(10000);
            });
            countDownLatch.countDown();
            countDownLatch.await();
            System.out.println(task1.get()+task2.get());
            LocalDateTime end = LocalDateTime.now();
            System.out.println("共耗时"+Duration.between(start,end).toMillis());
        }catch (InterruptedException e){
            System.out.println(e.getMessage());
        }catch (ExecutionException e){
            System.out.println(e.getMessage());
        }finally {
            executorService.shutdown();
        }
    }
    public static int sum(int num) throws InterruptedException {
        int sum = 0;
        for(int i=0;i<num;i++){
            sum = sum +i;
        }
        Thread.sleep(1000);
        return sum;
    }
}

6、Spring结合使用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值