首页 > 其他分享 >实际线程数量大于maximumPoolSize

实际线程数量大于maximumPoolSize

时间:2023-03-11 10:36:39浏览次数:48  
标签:thread maximumPoolSize 任务 线程 大于 执行 pool

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

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

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

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

    核心线程和临时线程都在忙、任务队列也满了、新任务过来时才会开始拒绝任务。
    
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);
    }

标签:thread,maximumPoolSize,任务,线程,大于,执行,pool
From: https://www.cnblogs.com/yfs1024/p/17205378.html

相关文章

  • 操作系统学习笔记2-进程和线程
    2.进程和线程2.0引入2.0.1顺序执行特征顺序性封闭性:独占整机资源可再现性:只要在相同的环境与初始条件下,执行结果相同顺序执行的场合:单道批处理系统2.0.2并......
  • 守护线程
    packagestate;publicclassTestDaemon{publicstaticvoidmain(String[]args){Godgod=newGod();Youyou=newYou();Thread......
  • 线程优先级
    packagestate;publicclassTestPoriority{publicstaticvoidmain(String[]args){MyPorioritymyPoriority=newMyPoriority();Thread......
  • 线程状态--礼让
    packagestate;//礼让不一定成功,看cpu调度publicclassTestYield{publicstaticvoidmain(String[]args){MyYieldmyYield=newMyYield();newThread(myYield,......
  • 线程状态--休眠
    packagestate;//模拟网络延时的作用:放大问题发生的可能性publicclassTestSleepimplementsRunnable{privateintticket=10;@Overridepublicvoid......
  • JAVA多线程处理大量数据(二)--推荐
    背景说明:要对服务器上一个目录进行全量文件读取1、多线程执行类--FileThreadUtils.javaimportcn.hutool.core.collection.CollUtil;importcn.hutool.core.io.FileUti......
  • 线程安全的map
    实现多线程下的insertfinderasebeginend等操作,输入的key或者value为指针的时候可以根据输入的releasefu回调实现内存释放/****************************************......
  • Excel多线程导出大数据量
    以下是Java的EasyExcelAPI实现多线程Excel导出的demo。在这个demo中,我们使用EasyExcelAPI来导出Excel文件。我们将表头和内容定义为动态的,以便能够处理大量的数据。我......
  • MFC-GetWindowThreadProcessId获取指定窗口线程ID和进程ID
     HWNDhWnd=::FindWindow(NULL,_T("sss.txt-记事本"));DWORDdwTID=0;DWORDdwPID=NULL;dwTID=::GetWindowThreadProcessId(hWnd,&dwPID......
  • java中的特殊文件、日志技术、多线程入门
    一,属性文件(.properties)1,特殊文件概述(必会)我们知道IO流是用来读数据,目的是为了获取其中的信息供我们使用,但是普通的txt文件是杂乱无章的,除非我们规定,自己写。虽然可以但......