实际线程数量大于maximumPoolSize

在做练习的时候出现了下面的状况

注:只是自己的推理哈,如果后面学会了看源码再补充和修改
首先复习两个知识:

  • 临时线程什么时候创建?

    新任务提交时,发现核心线程都在忙、任务队列满了、并且还可以创建临时线程,此时会创建临时线程。
    
  • 什么时候开始拒绝新的任务?

    核心线程和临时线程都在忙、任务队列也满了、新任务过来时才会开始拒绝任务。
    
public class TestThreadPoolExecutor {
    public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
            	1,  // 核心线程数 
            	3,  // 最大线程数
            	1,  // 临时线程允许空闲的时间
                TimeUnit.NANOSECONDS,  // 时间单位
                new ArrayBlockingQueue<>(3), // 阻塞队列的长度    默认为Integer.MAX
                Executors.defaultThreadFactory(), // 线程工厂
                new ThreadPoolExecutor.CallerRunsPolicy() // 处理策略 线程不够的时候主线程加入
        );
        // 执行16次
        for (int i = 1; i <= 16; i++) {
            // 执行16次任务
            pool.execute(new MyRunnable(i));
        }
        pool.shutdown();
    }
}

// 定义任务
class MyRunnable implements Runnable {
    private int i;
    public MyRunnable(int i) {
        this.i = i;
    }
    @Override
    public void run() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "  执行了任务" + i);
    }
}

控制台结果:

pool-1-thread-3  执行了任务6
pool-1-thread-2  执行了任务5
main  执行了任务7
pool-1-thread-1  执行了任务1
pool-1-thread-3  执行了任务2
pool-1-thread-2  执行了任务3
pool-1-thread-2  执行了任务9
pool-1-thread-3  执行了任务8
main  执行了任务10
pool-1-thread-1  执行了任务4
pool-1-thread-1  执行了任务11
pool-1-thread-5  执行了任务16   // 我最大的线程数 maximumPoolSize等于3为啥出现了第五个,第四个线程?
pool-1-thread-4  执行了任务14
pool-1-thread-5  执行了任务13
pool-1-thread-1  执行了任务12
pool-1-thread-4  执行了任务15

Process finished with exit code 0

刚开始的很是迷惑?啥情况,但是后来又想了想,可能是下面的情况

首先看到创建线程池的构造器的第三个参数为,1,第四个为TimeUnit.NANOSECONDS,也就是说1纳秒的时间,但是一般的计算机都是毫秒级别的。通过代码可以看到当有四个任务需要执行的时候,并且发现没有多的线程,此时就会去创建线程3,这个时候因为第七个参数,处理策略的原因主线程也加入进来。 又因为CPU是抢占式,所以顺序就不固定了,这里很好解释。但是第三和第四个参数设置的时间很短,这个时候创建出来的第三个线程就会销毁,然后最大线程数就会 maximumPoolSize - - ,问题应该就出在这个时候,此时的两个核心线程在工作,并且阻塞队列满了就会创建新的线程。就会去创建新的线程,这个时候如果这个方法没有实现线程同步,就会出现线程安全问题,即当上一个还没有 - - 之前就会出现此时已经进行了 maximumPoolSize++ 的操作 ,所以这个时候如果如果又抢到了cpu资源用于打印,这个时候就会出现线程4和线程5。当多个cpu多核处理的时候,如果线程没有同步的情况,就会出现这样的问题。

找了半天不知道是不是下面的地方没有实现线程同步:如果不是的话肯定有一个位置在做++操作的时候,没有实现同步,所以才导致的这个情况。

    private boolean compareAndIncrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect + 1);
    }

但是一般不会这么使用,因为创建线程就是用的,只允许人家休息一纳米,就把人家裁了,很不现实,浪费。只是做一个学习的分析过程的记录

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yfs1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值