首页 > 编程语言 > 详细

线程池的取值(三)阻塞队列边界取值

时间:2019-11-17 13:13:10      阅读:165      评论:0      收藏:0      [点我收藏+]

在上一篇中,线程池的取值(二)设计吞吐量 重要使用无界的LinkedBlockingQueue来接收等待队列,我们将阻塞队列改为36来看看:

 

import java.util.concurrent.*;

/**
 * https://www.cnblogs.com/silyvin/p/11806859.html
 * https://www.cnblogs.com/silyvin/p/11875907.html
 * Created by joyce on 2019/11/6.
 */
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.SECONDS)
@Threads(40)
@State(Scope.Thread)
public class MyThread {

    private static final ThreadPoolExecutor MQ_POOL = new ThreadPoolExecutor(
            4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(36),
            new DefaultThreadFactory("mq-", true));
    
    public static class action implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            int a = 0;
            Thread.sleep(2000);
            System.out.println(a);
            return a;
        }
    }

    @Benchmark
    public static void testS() {
        try {
            Future<Integer> i = MQ_POOL.submit(new action());
            i.get();
        } catch (RejectedExecutionException e) {
            System.out.println("放弃" + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String [] f) throws RunnerException {
        
        // jhm压力测试
        Options opt = new OptionsBuilder().include(MyThread.class.getSimpleName()).forks(1).warmupIterations(0)
                .measurementIterations(1).build();

        new Runner(opt).run();

        // 自己的压力测试
        MyYali.start(40);


    }

    private static class MyYali implements Runnable {

        public static void start(int threadCount) {

            for(int i=0; i<threadCount; ++i) {
                new Thread(new MyYali()).start();
            }
        }

        // 这个地方如果用1不会出错
        private int count = 2;

        @Override
        public void run() {
            for(int i=0; i<count; ++i) {
                testS();
            }
        }
    }
}

 

循环次数 2          jhm              自己压测

阻塞队列长度 36   多个放弃,响应时间28~19    1个放弃,相当稳定地每次出现在第4个打印“0”后

阻塞队列长度 37   没有放弃,响应时间20        没有放弃

 

循环次数 1        

阻塞队列长度 36      /                 没有放弃 

阻塞队列长度 37      /                没有放弃

  

 

放弃Task java.util.concurrent.FutureTask@1339fcef rejected from java.util.concurrent.ThreadPoolExecutor@300fa78c[Running, pool size = 4, active threads = 4, queued tasks = 35, completed tasks = 14]

 

所有根据现象推测,为什么36个线程就是出了拒绝,而且从手写的压测代码看,稳定的出现在第一批4个核心线程执行完,而且只出现一次

 

40个投递线程并发投递,4个线程抢到优先执行权,36个线程塞入长度为36的阻塞队列

第一个投递线程第一次循环执行完,但线程池还未将该坑位标志

第二个循环submit,发现核心4个坑和36个等待坑都满着,抛出放弃异常

技术分享图片

 

所以最佳实践就是,如果要求阻塞队列长度为n,实践层面将其设置为n+1

底层为何有这种现象,要等全面了解线程池源码后来解析

 

线程池的取值(三)阻塞队列边界取值

原文:https://www.cnblogs.com/silyvin/p/11875907.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!