`
deyimsf
  • 浏览: 68314 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

commons-pool-1.6部分源码分析

    博客分类:
  • java
阅读更多
类图关系

为了简单起见,该图只表现继承和实现关系



大部分情况下我们只使用ObjectPool和PoolableObjectFactory的相关实现类,我们重点分析GenricObjectPool类


配置参数

类GenericObjectPool.Config定义了相关参数:
// 池中最大空闲实例个数
int maxIdle=8

// 池中最小空闲实例个数 (evictor会用到)
int minIdle=0

// 可以从池中拿走的最多实例的个数,就是通常我们说的池大小
// 小于0则代表没有限制
int maxActive=8

// 当池耗尽并且whenExhaustedAction的值是WHEN_EXHAUSTED_BLOCK时候,
// borrowObject方法最大等待时间(毫秒),超过改时间则抛出异常
// (意思就是当池被耗尽时,从池中获取对象要等的时间)
// 小于0时一直阻塞
long maxWait = -1

// 当池被耗尽时,borrowObject方法应该采取的措施
byte whenExhaustedAction = WHEN_EXHAUSTED_BLOCK

// 默认是false,当是true得时候,borrowObject方法在返回之前
// 会调用自定义的PoolableObjectFactory.validateObject方法,校验
// 要返回的对象是否可用.如果不可用,该对象会被销毁,然后
// 会尝试生成另一个对象.
boolean testOnBorrow = false

// 默认是false,当时true的时候,当调用retruenObject将对象放回
// 池中时会调用PoolableObjectFactory.validateObject方法,校验对象   
// 是否可用. (如果不可用会销毁该对象) 
boolean testOnReturn = false
      
// 默认是fasle,当是true时,闲置对象驱逐器会调用validateObject
// 方法,校验对象是否可用,如果不可用会将其从池中drop掉
boolean testWhileIdle = false
        
// 闲置对象驱逐器运行的间隔时间(毫秒),如果是非正数则驱逐器将不会运行.
// (驱逐器可以确保池内对象不小于minIdle)
long timeBetweenEvictionRunsMillis = -1

// 驱逐器每次运行时检查池中闲置对象的最大个数
// (比如该值设置为3,此时池中有5个闲置对象,那么每次只会检查前三个闲置对象。
// 比如检查闲置对象是否可用等。ensureMinIdle()不受这个影响,因为是做完检查
// 后才执行ensureMinIdle)
int numTestsPerEvictionRun = 3

// 一个对象可以停留在池中的最少闲置时间,如果该对象在池中
// 的闲置时间大于该值,那么该对象就可以被驱逐器dorp掉。
// 如果是非正数,表示该对象可以一直闲置下去。(单位毫秒)
long minEvictableIdleTimeMillis = 1000L * 60L * 30L

// 和minEvictableIdleTimeMillis作用一样,但有一个额外条件:
// 如果池中闲置对象的个数不大于minIdle时,即使有对象的
// 闲置时间大于该设置的值也不会被dorp掉.
// 注意:如果minEvictableIdleTimeMillis>0则该参数就不在起作用.
long softMinEvictableIdleTimeMillis = -1

// 默认LIFO状态.true的意思是borrowObject方法返回池中的最近
// 使用过的闲置对象(如果该实例可用). fasle的意思是池是一个
// FIFO队列--对象从池中顺序的返回.
boolean lifo = true


从池中获取对象
从池中获取对象有borrowObject()方法负责,那么该方法到底做了什么?
public T borrowObject() throws Exception {
  long starttime = System.currentTimeMillis();
  Latch<T> latch = new Latch<T>();   //代表一个请求
  byte whenExhaustedAction;
  long maxWait;
  synchronized (this) {
      // Get local copy of current config. Can't sync when used later as
      // it can result in a deadlock. Has the added advantage that config
      // is consistent for entire method execution
      whenExhaustedAction = _whenExhaustedAction;
      maxWait = _maxWait;
  
      // Add this request to the queue
      // 请这个请求放入到请求对列.由下面的allocate()方法进行分配
      _allocationQueue.add(latch);
  }
  // Work the allocation queue, allocating idle instances and
  // instance creation permits in request arrival order
  //操作分配队列 ,为请求顺序分配空闲实例和实例创建许可     
  allocate();
  
  for(;;) {
      synchronized (this) {
          assertOpen();
      }
  
      // If no object was allocated from the pool above
      // 没有从池中分配出一个池对象
      if(latch.getPair() == null) {
        // check if we were allowed to create one
        // 检查是否允许创建一个池对象
        if(latch.mayCreate()) {
            // allow new object to be created
            // 允许创建一个池对象
        } else {
          // the pool is exhausted
          // 池被耗尽时执行以下耗尽策略
          switch(whenExhaustedAction) {
            case WHEN_EXHAUSTED_GROW:  //该策略可以忽略不能创建新池对象的限制
              // allow new object to be created
              synchronized (this) {
                 // Make sure another thread didn't allocate us an object
                 // or permit a new object to be created
              	 // 确保这是其他线程没有给当前请求(latch)关联一个池对象
                 // 或者授权可创建新对象
                 if (latch.getPair() == null && !latch.mayCreate()) {
                     //将请求从请求队列中移除,这时该请求就变为可用请求
                     _allocationQueue.remove(latch); 
                     _numInternalProcessing++;
                 }
              }
              break;
            case WHEN_EXHAUSTED_FAIL:  //该策略直接抛异常
              synchronized (this) {
                 // Make sure allocate hasn't already assigned an object
                 // in a different thread or permitted a new object to 
                 // be created
                 if (latch.getPair() != null || latch.mayCreate()) {
                     break;
                 }
                 _allocationQueue.remove(latch);
              }
              throw new NoSuchElementException("Pool exhausted");
            case WHEN_EXHAUSTED_BLOCK: //该策略让请求等待一段时间
              try {
                 // 该同步块用latch作为锁原因:
                 // 1.和allocate()方法中的latch同步块配合;
                 // 2.减小锁的范围,如果都用this锁,那么走到这里时所有的线程都要
                 // 顺序执行,但是用latch就不用,因为各个线程持有的锁(latch)不一样
                 // 所以这里对不同的线程可以并发执行。
                 synchronized (latch) {
                     // Before we wait, make sure another thread didn't 
                     // allocate us an object
                     // or permit a new object to be created
                     // 等待之前确保其他线程没有给分配一个池对象或授权创建新池对象
                     if (latch.getPair() == null && !latch.mayCreate()) {
                         if(maxWait <= 0) {  //最大等待时间小于等于0就一直等待
                             latch.wait();
                         } else {  //计算需要等待的时间并执行等待
                             // this code may be executed again after a 
                             // notify then continue cycle
                             // so, need to calculate the amount of time 
                             //to wait
                             final long elapsed = (System.currentTimeMillis() - starttime);
                             final long waitTime = maxWait - elapsed;
                             if (waitTime > 0){
                                 latch.wait(waitTime);
                             }
                         }
                     } else {
                         break;
                     }
                 }
                 // see if we were awakened by a closing pool
                 if(isClosed() == true) {
                     throw new IllegalStateException("Pool closed");
                 }
              } catch(InterruptedException e) { //被其他线程提前中断
                 boolean doAllocate = false;
                 synchronized(this) {
                     // Need to handle the all three possibilities
                     // 需要处理三种可能性
                     if (latch.getPair() == null && !latch.mayCreate()) {
                         // Case 1: latch still in allocation queue
                         // Remove latch from the allocation queue
                         // 情况1:请求仍然在请求队列,还没有分配池对象
                         _allocationQueue.remove(latch);
                     } else if (latch.getPair() == null 
                                             && latch.mayCreate()) {
                         //Case 2:latch has been given permission to create
                         //         a new object
                         //情况2:请求已经被赋予可以创建新池对象
                         _numInternalProcessing--;
                         //腾出一个坑儿,让给别人
                         doAllocate = true;
                     } else {
                         // Case 3: An object has been allocated
                         //  情况3:请求已经分配了一个池对象
                         _numInternalProcessing--;
                         //下面的returnObject方法会将该值减一,所以这里先加一
                         _numActive++;   
                         //以上两句可以理解为将关联池对象返回给了外部
                         //而这语句表示将外部的池对象放入到池中
                         returnObject(latch.getPair().getValue());
                     }
                 }
                 if (doAllocate) {
                     allocate();
                 }
                 
                 //发生中断异常后,中断状态已经被清除.
                 //重置线程中断状态
                 Thread.currentThread().interrupt(); //?
                 throw e;
              }
              
              // 如果线程等待超时、产生虚假唤醒(没有被通知、中断或超时)
              // 或者其他线程调用latch.notify则会走到这一步
              if(maxWait > 0 
                    && ((System.currentTimeMillis() - starttime) 
                              >= maxWait)) {// 超时
                 synchronized(this) {
                    // Make sure allocate hasn't already assigned an object
                    // in a different thread or permitted a new object to 
                    // be created
                    //超时后仍没有获取到一个关联池对象或者新创建许可
                    if (latch.getPair() == null && !latch.mayCreate()) {
                        // Remove latch from the allocation queue
                        _allocationQueue.remove(latch);
                    } else {//在等待的过程中获取到一个关联池对象或者新创建许可
                        break;
                    }
                 }
                 throw new NoSuchElementException("Timeout waiting "+
                                                       "for idle object");
              } else { //虚假唤醒或其它线程调用了latch.notify
                 continue; // keep looping
              }
            default:
                throw new IllegalArgumentException("WhenExhaustedAction property " +
                        whenExhaustedAction +" not recognized.");
          }
        }
      }
  
      // 走到这里说明允许创建一个新池对象或者已经关联了一个池对象
      boolean newlyCreated = false;  //是否已经创建了池对象
      if(null == latch.getPair()) { //没有关联一个吃对象,但是允许创建一个池对象
          try {
              T obj = _factory.makeObject();
              latch.setPair(new ObjectTimestampPair<T>(obj));  //关联池对象
              newlyCreated = true;
          } finally {
              if (!newlyCreated) {//池对象创建失败
                  //object cannot be created
                  //因为之前在allocate()方法中在设置_mayCreate值时
                  //将_numInternalProcessing++
                  //所以如果创建池对象失败就将可用请求个数减一
                  synchronized (this) {
                      _numInternalProcessing--;
                      // No need to reset latch - about to throw exception
                  }
                  
                  // 腾出来一个坑儿,让给其他人
                  allocate();
              }
          }
      }
      // activate & validate the object
      // 走到这里说明已经获取到了一个池对象(新创建的或者从池中拿的)
      // 激活和校验池对象是否可用
      try {
          _factory.activateObject(latch.getPair().value);
          
          //只有_testOnBorrow值为true时才对关联的池对象进行校验
          if(_testOnBorrow &&
                  !_factory.validateObject(latch.getPair().value)) {
              throw new Exception("ValidateObject failed");
          }
          
          //池对象返回给外部前,可用请求个数减一,池外活跃对象个数加一
          synchronized(this) {
              _numInternalProcessing--;
              _numActive++;
          }
          
          //返回池对象
          return latch.getPair().value;
      } catch (Throwable e) { //??
          PoolUtils.checkRethrow(e);//??
          // object cannot be activated or is invalid
          // 池对象不能被激活或者校验失败
          try {
              _factory.destroyObject(latch.getPair().value);
          } catch (Throwable e2) {
              PoolUtils.checkRethrow(e2);
              // cannot destroy broken object
          }
          synchronized (this) {
              _numInternalProcessing--;
              // 请求已关联到一个池对象,但是池对象不可用
              if (!newlyCreated) {
              	//重置请求,并将该请求放入到请求队列
              	//后续再调用一次allocate()方法继续从池中拿空闲对象
                  latch.reset();
                  _allocationQueue.add(0, latch);
              }
          }
          allocate();
          //走到这里并且newlyCreated=true
          //那么说明池中已经没有空闲对象,并且新创建的池对象不可用,那么直接抛异常
          if(newlyCreated) {
              throw new NoSuchElementException("Could not create a validated "+
                                        "object,"+ " cause: " + e.getMessage());
          //走到这里且newlyCreated=false
          //说明请求(latch)从池中获取的对象不可用,那么继续循环从池中寻找空闲对象
          //如果池中没有空闲对象并且也不允许再创建新池对象,
          //那么会进入池耗尽策略switch(whenExhaustedAction)代码块
          }else {  
              continue; // keep looping
          }
      }
  }
}
 


我们可以看到borrowObject方法中又很多地方都调用了一个内部函数allocate(),
该方法主要负责为每一个请求(latch)分配对象,具体实现如下:

private synchronized void allocate() {
        if (isClosed()) return;

        // First use any objects in the pool to clear the queue
        // 首先,用池中的对象给请求队列中的请求分配对象
        for (;;) {
            //如果有请求队列有请求,且池中又空闲对象
            if (!_pool.isEmpty() && !_allocationQueue.isEmpty()) {
                Latch<T> latch = _allocationQueue.removeFirst();
                latch.setPair( _pool.removeFirst());  //从池中拿走一个对象给请求(latch)
                _numInternalProcessing++;   //正在分配中得对象的个数
                synchronized (latch) {
                	//当池中对象已经耗尽且when_exhausted_block值是WHEN_EXHAUSTED_BLOCK
                	//这个时候来的请求会根据过期时间在同步块中等待。
                	//这语句让让等待(latch.wait(xxx))的请求激活
                    latch.notify();	
                }
            } else {  //跳出,直到将池中得对象分配完毕
                break;
            }
        }

        // Second  any spare capacity to create new objects
        // 然后,根据池的配置决定是否可以为请求队列中的请求(latch)创建新的池对象
        for(;;) {
            //_maxActive 最大活跃对象个数
            //_numActive 当前在池外的活跃对象个数
            //_numInternalProcessing 可用请求(已分配池对象或_mayCreate标记为true的latch)的个数
            if((!_allocationQueue.isEmpty()) && (_maxActive < 0
                     || (_numActive + _numInternalProcessing) < _maxActive)) {
                Latch<T> latch = _allocationQueue.removeFirst();
                latch.setMayCreate(true);  //设置该请求(latch)的可创建标志为true
                _numInternalProcessing++;
                synchronized (latch) {
                	//通知等待的latch可以创建池对象了
                    latch.notify();	
                }
            } else {
                break;
            }
        }
    } 




未完待续...
  • 大小: 86.7 KB
分享到:
评论
1 楼 a912770106 2015-05-12  
分析的很好,讲的很清楚,希望后面的能分析完

相关推荐

    dbcp 1.4 jar 和 源码

    4. **源码分析** - `commons-dbcp-1.4-bin.zip` 包含了DBCP的编译后的JAR文件,供应用程序直接使用。 - `commons-dbcp-1.4-src.zip` 提供了DBCP的源代码,可以用于学习其内部实现,进行调试或定制修改。 5. **...

    果壳处理器研究小组(Topic基于RISCV64果核处理器的卷积神经网络加速器研究)详细文档+全部资料+优秀项目+源码.zip

    【资源说明】 果壳处理器研究小组(Topic基于RISCV64果核处理器的卷积神经网络加速器研究)详细文档+全部资料+优秀项目+源码.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    JSP学生学籍管理系统(源代码+论文+开题报告+外文翻译+答辩PPT)(2024x5).7z

    1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于计算机科学与技术等相关专业,更为适合;

    LabVIEW实现NB-IoT通信【LabVIEW物联网实战】

    资源说明:https://blog.csdn.net/m0_38106923/article/details/144637354 一分价钱一分货,项目代码可顺利编译运行~

    【java毕业设计】智慧社区综合平台(源代码+论文+PPT模板).zip

    有java环境就可以运行起来 ,zip里包含源码+论文+PPT, 系统设计与功能: 文档详细描述了系统的后台管理功能,包括系统管理模块、新闻资讯管理模块、公告管理模块、社区影院管理模块、会员上传下载管理模块以及留言管理模块。 系统管理模块:允许管理员重新设置密码,记录登录日志,确保系统安全。 新闻资讯管理模块:实现新闻资讯的添加、删除、修改,确保主页新闻部分始终显示最新的文章。 公告管理模块:类似于新闻资讯管理,但专注于主页公告的后台管理。 社区影院管理模块:管理所有视频的添加、删除、修改,包括影片名、导演、主演、片长等信息。 会员上传下载管理模块:审核与删除会员上传的文件。 留言管理模块:回复与删除所有留言,确保系统内的留言得到及时处理。 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7及以上 数据库工具:Navicat11及以上 开发软件:eclipse/idea Maven包:Maven3.3及以上

    基于python3+selenium+unittest的WebUI自动化测试框架,使用POM(页面对象模型)设计模式,适合几乎所有web项目,资料齐全+详细文档

    【资源说明】 基于python3+selenium+unittest的WebUI自动化测试框架,使用POM(页面对象模型)设计模式,适合几乎所有web项目,可集成Jenkins部署自动化测试资料齐全+详细文档+高分项目+源码.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    智能车开发案例,使用Python语言在一个文件中实现 这里我们将添加一些额外的功能,如自动驾驶模式、避障、超声波传感器读取以及通过TCP/IP网络远程控制

    智能车开发案例,使用Python语言在一个文件中实现。这里我们将添加一些额外的功能,如自动驾驶模式、避障、超声波传感器读取以及通过TCP/IP网络远程控制。 首先,确保你已经安装了pyserial、socket库: pip install pyserial

    屏幕截图 2024-12-21 165859.png

    屏幕截图 2024-12-21 165859

    电缆、树木检测15-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rar

    电缆、树木检测15-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rarPL + VG-V4 2024-01-04 6:04 PM ============================= *与您的团队在计算机视觉项目上合作 *收集和组织图像 *了解和搜索非结构化图像数据 *注释,创建数据集 *导出,训练和部署计算机视觉模型 *使用主动学习随着时间的推移改善数据集 对于最先进的计算机视觉培训笔记本,您可以与此数据集一起使用 该数据集包括5082张图像。 Powerlines-Tree以可可格式注释。 将以下预处理应用于每个图像: *调整大小为640x640(拉伸) 应用以下扩展用于创建每个源图像的2个版本: *水平翻转的50%概率 *垂直翻转的50%概率 *以下90度旋转之一的同等概率:无,顺时针,逆时针方向

    【湍流】基于matlab RANS湍流通道流【含Matlab源码 9913期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    基于python的代码会生成一个简单的圣诞树图形

    圣诞树代码 这段代码会生成一个简单的圣诞树图形,包括: 三层树冠,使用不同深度的绿色。 一个棕色的树干。 一颗黄色的星星作为树顶。 随机分布的彩色小圆点作为装饰。 请确保你已经安装了matplotlib库,如果没有,可以通过pip install matplotlib来安装。运行这段代码后,你应该能看到一个圣诞树的图形。

    jsp网上超市设计与实现(源代码+论文)(2024cq).7z

    1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于计算机科学与技术等相关专业,更为适合;

    基于 Node.js、MongoDB、Redis 开发的系统小商城后台全部资料+详细文档+源码+高分项目.zip

    【资源说明】 基于 Node.js、MongoDB、Redis 开发的系统小商城后台全部资料+详细文档+源码+高分项目.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    【java毕业设计】智慧社区停车管理系统(源代码+论文+PPT模板).zip

    zip里包含源码+论文+PPT,有java环境就可以运行起来 ,功能说明: 文档开篇阐述了随着计算机技术、通信技术和网络技术的快速发展,智慧社区门户网站的建设成为了可能,并被视为21世纪信息产业的主要发展方向之一 强调了网络信息管理技术、数字化处理技术和数字式信息资源建设在国际竞争中的重要性。 指出了智慧社区门户网站系统的编程语言为Java,数据库为MYSQL,并实现了新闻资讯、社区共享、在线影院等功能。 系统设计与功能: 文档详细描述了系统的后台管理功能,包括系统管理模块、新闻资讯管理模块、公告管理模块、社区影院管理模块、会员上传下载管理模块以及留言管理模块。 系统管理模块:允许管理员重新设置密码,记录登录日志,确保系统安全。 新闻资讯管理模块:实现新闻资讯的添加、删除、修改,确保主页新闻部分始终显示最新的文章。 公告管理模块:类似于新闻资讯管理,但专注于主页公告的后台管理。 社区影院管理模块:管理所有视频的添加、删除、修改,包括影片名、导演、主演、片长等信息。 会员上传下载管理模块:审核与删除会员上传的文件。 留言管理模块:回复与删除所有留言,确保系统内的留言得到及时处理。

    ECharts散点图-日历图.zip

    ECharts散点图-日历图

    【java毕业设计】智慧社区智慧站点(源代码+论文+PPT模板).zip

    有java环境就可以运行起来 ,zip里包含源码+论文+PPT, 系统设计与功能: 文档详细描述了系统的后台管理功能,包括系统管理模块、新闻资讯管理模块、公告管理模块、社区影院管理模块、会员上传下载管理模块以及留言管理模块。 系统管理模块:允许管理员重新设置密码,记录登录日志,确保系统安全。 新闻资讯管理模块:实现新闻资讯的添加、删除、修改,确保主页新闻部分始终显示最新的文章。 公告管理模块:类似于新闻资讯管理,但专注于主页公告的后台管理。 社区影院管理模块:管理所有视频的添加、删除、修改,包括影片名、导演、主演、片长等信息。 会员上传下载管理模块:审核与删除会员上传的文件。 留言管理模块:回复与删除所有留言,确保系统内的留言得到及时处理。 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7及以上 数据库工具:Navicat11及以上 开发软件:eclipse/idea Maven包:Maven3.3及以上

    四川采矿场消防管理规定.docx

    四川采矿场消防管理规定

    【java毕业设计】智慧社区智能家居门户.zip

    有java环境就可以运行起来 ,zip里包含源码+论文+PPT, 系统设计与功能: 文档详细描述了系统的后台管理功能,包括系统管理模块、新闻资讯管理模块、公告管理模块、社区影院管理模块、会员上传下载管理模块以及留言管理模块。 系统管理模块:允许管理员重新设置密码,记录登录日志,确保系统安全。 新闻资讯管理模块:实现新闻资讯的添加、删除、修改,确保主页新闻部分始终显示最新的文章。 公告管理模块:类似于新闻资讯管理,但专注于主页公告的后台管理。 社区影院管理模块:管理所有视频的添加、删除、修改,包括影片名、导演、主演、片长等信息。 会员上传下载管理模块:审核与删除会员上传的文件。 留言管理模块:回复与删除所有留言,确保系统内的留言得到及时处理。 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7及以上 数据库工具:Navicat11及以上 开发软件:eclipse/idea Maven包:Maven3.3及以上

    荒地、水体、农田、湖检测14-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rar

    荒地、水体、农田、湖检测14-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rarTAAL-TERRAIN-V6 2022-12-03下午5:58 ============================= *与您的团队在计算机视觉项目上合作 *收集和组织图像 *了解非结构化图像数据 *注释,创建数据集 *导出,训练和部署计算机视觉模型 *使用主动学习随着时间的推移改善数据集 它包括4115张图像。 地形以可可格式注释。 将以下预处理应用于每个图像: *像素数据的自动取向(带有Exif-Arientation剥离) *调整大小为640x640(拉伸) 应用以下扩展来创建每个源图像的3个版本: *水平翻转的50%概率 *垂直翻转的50%概率 *以下90度旋转之一的同等概率:无,顺时针,逆时针,颠倒

    python hhhhhhhh

    python hhhhhhhh

Global site tag (gtag.js) - Google Analytics