java线程池关闭问题

本文探讨了Java中线程池的关闭问题,分析了局部变量和成员变量方式创建线程池的优缺点。针对线程池的优雅关闭,介绍了通过设置keepAliveTime来控制线程存活时间,实现线程的自动终止。讨论了两种情况:一是仅关闭超出核心线程的线程,二是允许核心线程超时关闭。通过实例展示了不同配置下线程的生命周期和关闭行为。
摘要由CSDN通过智能技术生成

一、线程池关闭问题

1、我们知道下面这段代码,线程池作为局部变量使用,是没有意义的。每次进来请求都是创建一个线程池后,销毁线程,关闭线程池。然后在来一个请求,再次创建一个线程池,在关闭线程。

 @RequestMapping("/test")
    public String test() {
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(5, 5,
                10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(50));
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + Thread.currentThread().getId());
            }
        });
        executorService.shutdown();
        return "hello world";
    }

2、现在我们把线程池设置为成员变量,我们看到方法的最后关闭了线程executorService.shutdown() 但是关闭后就不能有新的请求过来了, 如果我们不关闭,线程会一直存活,最后随着请求的增多会造成OOM

private ThreadPoolExecutor executorService = new ThreadPoolExecutor(5, 5,
            10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(50));

    @RequestMapping("/test")
    public String test() {
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + Thread.currentThread().getId());
            }
        });
        executorService.shutdown();
        return "hello world";
    }

二、如何优雅的关闭线程呢?
自定义线程池,并设置keepAliveTime线程的存活时间

keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;

1、存活时间到了后,只关闭超出核心线程的线程

这里我们设置核心线程1个,最多线程5个,存活时间10s, 为了演示超出核心线程再去创建线程,队列设置1

private ThreadPoolExecutor executorService = new ThreadPoolExecutor(1, 5,
            10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));

    @RequestMapping("/test")
    public String test() {
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(5);
                }catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + Thread.currentThread().getId());
            }
        });

        return "hello world";
    }

下图可以看到一直存活的线程是核心线程。超出核心线程以外的线程等到10s后就销毁了
在这里插入图片描述
2、存活时间到了后,销毁所有线程(包括核心线程)
这里我们executorService.allowCoreThreadTimeOut(true) 设置后,存活时间到了后会销毁所有线程

private ThreadPoolExecutor executorService = new ThreadPoolExecutor(1, 5,
            10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1));

    @RequestMapping("/test")
    public String test() {
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(5);
                }catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + Thread.currentThread().getId());
            }
        });
        executorService.allowCoreThreadTimeOut(true);
        return "hello world";
    }

下图可以看到所有线程都销毁了
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值