一个程序员的成长

一个程序员的成长

  • 我们使用了有界的队列,那么当队列满了之后如何处理后面进入的请求,我们可以通过不同的策略进行设置。

    4种拒绝策略

    接下来我们来创建一个容错率比较高的线程池。

    public class WordTest {

        public static void main(String[] args) throws InterruptedException {

            System.out.println("开始执行");

            // 阻塞队列容量声明为100个
            ThreadPoolExecutor executorService = new ThreadPoolExecutor(10, 10,
                    0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(100));

            // 设置拒绝策略
            executorService.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            // 空闲队列存活时间
            executorService.setKeepAliveTime(20, TimeUnit.SECONDS);

            List<Integer> list = new ArrayList<>(2000);

            try {
                // 模拟200个请求
                for (int i = 0; i < 200; i++) {
                    final int num = i;
                    executorService.execute(() -> {
                        System.out.println(Thread.currentThread().getName() + "-结果:" + num);
                        list.add(num);
                    });
                }
            } finally {
                executorService.shutdown();
                executorService.awaitTermination(10, TimeUnit.SECONDS);
            }
            System.out.println("线程执行结束");
        }
    }

    思路:我声明了100容量的阻塞队列,模拟了一个200的请求,很显然肯定有部分请求进入不了队列,但是我使用了CallerRunsPolicy策略,当队列满了之后,使用主线程去进行处理,这样就不会出现有部分请求得不到执行的情况,也不会因为因为阻塞队列过大导致内存溢出的情况。

    通过测试200个请求全部得到执行,有3个请求由主线程进行了处理。

    总结

    如何更好的创建线程池上面已经说过了,关于线程池在业务中的使用,其实我们这种全局的思路是不太好的,因为如果从全局考虑去创建线程池,是很难把控的,因为你无法准确地评估所有的请求加起来会有多大的量,所以最好是每个业务创建独立的线程池进行处理,这样是很容易评估量化的。

    另外创建的时候,最好评估下大概每秒的请求量有多少,然后来合理的初始化线程数和队列大小。

    日拱一卒,功不唐捐


    Executors使用不当引起的内存泄漏-LMLPHP


    本文分享自微信公众号 - 一个程序员的成长(xiaozaibuluo)。
    如有侵权,请联系 support@oschina.cn 删除。
    本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

    03-07 18:08