yolo-world 源码解析(三)(3)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: yolo-world 源码解析(三)

yolo-world 源码解析(三)(2)https://developer.aliyun.com/article/1483864

.\YOLO-World\configs\segmentation\yolo_world_seg_m_dual_vlpan_2e-4_80e_8gpus_seghead_finetune_lvis.py

_base_ = (
    '../../third_party/mmyolo/configs/yolov8/yolov8_m_mask-refine_syncbn_fast_8xb16-500e_coco.py'
)
# 定义基础配置文件路径
custom_imports = dict(imports=['yolo_world'], allow_failed_imports=False)
# 自定义导入模块,禁止导入失败
# 超参数设置
num_classes = 1203
num_training_classes = 80
max_epochs = 80  # 最大训练轮数
close_mosaic_epochs = 10
save_epoch_intervals = 5
text_channels = 512
neck_embed_channels = [128, 256, _base_.last_stage_out_channels // 2]
neck_num_heads = [4, 8, _base_.last_stage_out_channels // 2 // 32]
base_lr = 2e-4
weight_decay = 0.05
train_batch_size_per_gpu = 8
load_from = 'pretrained_models/yolo_world_m_clip_base_dual_vlpan_2e-3adamw_32xb16_100e_o365_goldg_train_pretrained-2b7bd1be.pth'
persistent_workers = False
# Polygon2Mask
downsample_ratio = 4
mask_overlap = False
use_mask2refine = True
max_aspect_ratio = 100
min_area_ratio = 0.01
# 模型设置
model = dict(
    type='YOLOWorldDetector',
    mm_neck=True,
    num_train_classes=num_training_classes,
    num_test_classes=num_classes,
    data_preprocessor=dict(type='YOLOWDetDataPreprocessor'),
    backbone=dict(
        _delete_=True,
        type='MultiModalYOLOBackbone',
        image_model={{_base_.model.backbone}},
        frozen_stages=4,  # 冻结图像骨干网络的阶段
        text_model=dict(
            type='HuggingCLIPLanguageBackbone',
            model_name='openai/clip-vit-base-patch32',
            frozen_modules=['all'])),
    neck=dict(type='YOLOWorldDualPAFPN',
              freeze_all=True,
              guide_channels=text_channels,
              embed_channels=neck_embed_channels,
              num_heads=neck_num_heads,
              block_cfg=dict(type='MaxSigmoidCSPLayerWithTwoConv'),
              text_enhancder=dict(type='ImagePoolingAttentionModule',
                                  embed_channels=256,
                                  num_heads=8)),
    # 定义一个字典,包含YOLOWorldSegHead的相关参数
    bbox_head=dict(type='YOLOWorldSegHead',
                   head_module=dict(type='YOLOWorldSegHeadModule',
                                    embed_dims=text_channels,
                                    num_classes=num_training_classes,
                                    mask_channels=32,
                                    proto_channels=256,
                                    freeze_bbox=True),
                   mask_overlap=mask_overlap,
                   loss_mask=dict(type='mmdet.CrossEntropyLoss',
                                  use_sigmoid=True,
                                  reduction='none'),
                   loss_mask_weight=1.0),
    # 定义训练配置,包含分配器的参数
    train_cfg=dict(assigner=dict(num_classes=num_training_classes)),
    # 定义测试配置,包含mask_thr_binary和fast_test参数
    test_cfg=dict(mask_thr_binary=0.5, fast_test=True))
# 定义数据预处理流程的起始部分
pre_transform = [
    # 加载图像文件
    dict(type='LoadImageFromFile', backend_args=_base_.backend_args),
    # 加载标注信息,包括边界框和掩码
    dict(type='LoadAnnotations',
         with_bbox=True,
         with_mask=True,
         mask2bbox=True)
]
# 定义数据预处理流程的最后部分
last_transform = [
    # 使用 mmdet 库中的 Albu 进行数据增强
    dict(type='mmdet.Albu',
         transforms=_base_.albu_train_transforms,
         bbox_params=dict(type='BboxParams',
                          format='pascal_voc',
                          label_fields=['gt_bboxes_labels',
                                        'gt_ignore_flags']),
         keymap={
             'img': 'image',
             'gt_bboxes': 'bboxes'
         }),
    # 使用 YOLOv5HSVRandomAug 进行数据增强
    dict(type='YOLOv5HSVRandomAug'),
    # 随机翻转图像
    dict(type='mmdet.RandomFlip', prob=0.5),
    # 将多边形转换为掩码
    dict(type='Polygon2Mask',
         downsample_ratio=downsample_ratio,
         mask_overlap=mask_overlap),
]
# 数据集设置
text_transform = [
    # 随机加载文本信息
    dict(type='RandomLoadText',
         num_neg_samples=(num_classes, num_classes),
         max_num_samples=num_training_classes,
         padding_to_max=True,
         padding_value=''),
    # 打包检测输入信息
    dict(type='PackDetInputs',
         meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape', 'flip',
                    'flip_direction', 'texts'))
]
mosaic_affine_transform = [
    # 多模态镶嵌
    dict(type='MultiModalMosaic',
         img_scale=_base_.img_scale,
         pad_val=114.0,
         pre_transform=pre_transform),
    # YOLOv5CopyPaste 数据增强
    dict(type='YOLOv5CopyPaste', prob=_base_.copypaste_prob),
    # YOLOv5RandomAffine 数据增强
    dict(
        type='YOLOv5RandomAffine',
        max_rotate_degree=0.0,
        max_shear_degree=0.0,
        max_aspect_ratio=100.,
        scaling_ratio_range=(1 - _base_.affine_scale, 1 + _base_.affine_scale),
        # 图像缩放比例为 (宽度, 高度)
        border=(-_base_.img_scale[0] // 2, -_base_.img_scale[1] // 2),
        border_val=(114, 114, 114),
        min_area_ratio=_base_.min_area_ratio,
        use_mask_refine=True)
]
# 训练流程
train_pipeline = [
    # 将数据预处理流程的起始部分和多模态仿射变换部分合并
    *pre_transform, *mosaic_affine_transform,
    # 创建一个字典,指定模型类型为YOLOv5MultiModalMixUp,概率为mixup_prob
    dict(type='YOLOv5MultiModalMixUp',
         prob=_base_.mixup_prob,
         # 将pre_transform和mosaic_affine_transform的元素合并到一个列表中
         pre_transform=[*pre_transform, *mosaic_affine_transform]),
    # 将last_transform和text_transform的元素合并到一个列表中
    *last_transform, *text_transform
# 定义训练管道的第二阶段,包括预处理、YOLOv5KeepRatioResize、LetterResize、YOLOv5RandomAffine等操作
_train_pipeline_stage2 = [
    *pre_transform,  # 将pre_transform中的操作展开
    dict(type='YOLOv5KeepRatioResize', scale=_base_.img_scale),  # 使用YOLOv5KeepRatioResize进行图像缩放
    dict(type='LetterResize',  # 使用LetterResize进行图像缩放
         scale=_base_.img_scale,  # 图像缩放比例
         allow_scale_up=True,  # 允许图像放大
         pad_val=dict(img=114.0)),  # 图像填充值
    dict(type='YOLOv5RandomAffine',  # 使用YOLOv5RandomAffine进行随机仿射变换
         max_rotate_degree=0.0,  # 最大旋转角度
         max_shear_degree=0.0,  # 最大剪切角度
         scaling_ratio_range=(1 - _base_.affine_scale, 1 + _base_.affine_scale),  # 缩放比例范围
         max_aspect_ratio=_base_.max_aspect_ratio,  # 最大长宽比
         border_val=(114, 114, 114),  # 边界填充值
         min_area_ratio=min_area_ratio,  # 最小区域比例
         use_mask_refine=use_mask2refine),  # 是否使用mask进行细化
    *last_transform  # 将last_transform中的操作展开
]
# 将_train_pipeline_stage2和text_transform合并为train_pipeline_stage2
train_pipeline_stage2 = [*_train_pipeline_stage2, *text_transform]
# 定义coco_train_dataset,包括数据集类型、数据根目录、注释文件、数据前缀等信息
coco_train_dataset = dict(
    _delete_=True,  # 删除标记
    type='MultiModalDataset',  # 数据集类型
    dataset=dict(type='YOLOv5LVISV1Dataset',  # 数据集类型为YOLOv5LVISV1Dataset
                 data_root='data/coco',  # 数据根目录
                 ann_file='lvis/lvis_v1_train_base.json',  # 注释文件
                 data_prefix=dict(img=''),  # 数据前缀
                 filter_cfg=dict(filter_empty_gt=True, min_size=32)),  # 过滤配置
    class_text_path='data/captions/lvis_v1_base_class_captions.json',  # 类别文本路径
    pipeline=train_pipeline)  # 数据处理管道
# 定义train_dataloader,包括持久化工作进程、每个GPU的训练批量大小、数据集、数据集合并函数等信息
train_dataloader = dict(persistent_workers=persistent_workers,  # 持久化工作进程
                        batch_size=train_batch_size_per_gpu,  # 每个GPU的训练批量大小
                        collate_fn=dict(type='yolow_collate'),  # 数据集合并函数
                        dataset=coco_train_dataset)  # 数据集
# 定义测试管道,包括加载文本、PackDetInputs等操作
test_pipeline = [
    *_base_.test_pipeline[:-1],  # 将_base_.test_pipeline中的操作展开,去掉最后一个操作
    dict(type='LoadText'),  # 加载文本
    dict(type='mmdet.PackDetInputs',  # 使用mmdet.PackDetInputs打包检测输入
         meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',  # 元数据键
                    'scale_factor', 'pad_param', 'texts'))  # 元数据键
]
# 默认的钩子配置,包括参数调度器和检查点
default_hooks = dict(param_scheduler=dict(scheduler_type='linear',
                                          lr_factor=0.01,
                                          max_epochs=max_epochs),
                     checkpoint=dict(max_keep_ckpts=-1,
                                     save_best=None,
                                     interval=save_epoch_intervals))
# 自定义的钩子配置
custom_hooks = [
    dict(type='EMAHook',
         ema_type='ExpMomentumEMA',
         momentum=0.0001,
         update_buffers=True,
         strict_load=False,
         priority=49),
    dict(type='mmdet.PipelineSwitchHook',
         switch_epoch=max_epochs - close_mosaic_epochs,
         switch_pipeline=train_pipeline_stage2)
]
# 训练配置,包括最大训练周期、验证间隔、动态间隔
train_cfg = dict(max_epochs=max_epochs,
                 val_interval=5,
                 dynamic_intervals=[((max_epochs - close_mosaic_epochs),
                                     _base_.val_interval_stage2)])
# 优化器包装器配置,包括优化器类型、学习率、权重衰减
optim_wrapper = dict(optimizer=dict(
    _delete_=True,
    type='AdamW',
    lr=base_lr,
    weight_decay=weight_decay,
    # 设置每个 GPU 的训练批量大小
    batch_size_per_gpu=train_batch_size_per_gpu),
    # 针对参数进行配置,设置偏置和归一化的衰减倍数为0
    paramwise_cfg=dict(bias_decay_mult=0.0,
                       norm_decay_mult=0.0,
                       custom_keys={
                           # 针对文本模型的学习率倍数设置为0.01
                           'backbone.text_model':
                           dict(lr_mult=0.01),
                           # 针对logit_scale的权重衰减设置为0.0
                           'logit_scale':
                           dict(weight_decay=0.0),
                           # 针对neck的学习率倍数设置为0.0
                           'neck':
                           dict(lr_mult=0.0),
                           # 针对head_module.reg_preds的学习率倍数设置为0.0
                           'head.head_module.reg_preds':
                           dict(lr_mult=0.0),
                           # 针对head_module.cls_preds的学习率倍数设置为0.0
                           'head.head_module.cls_preds':
                           dict(lr_mult=0.0),
                           # 针对head_module.cls_contrasts的学习率倍数设置为0.0
                           'head.head_module.cls_contrasts':
                           dict(lr_mult=0.0)
                       }),
    # 设置构造函数为'YOLOWv5OptimizerConstructor'
    constructor='YOLOWv5OptimizerConstructor')
# 设置评估参数
coco_val_dataset = dict(
    _delete_=True,  # 删除该参数
    type='MultiModalDataset',  # 数据集类型为多模态数据集
    dataset=dict(type='YOLOv5LVISV1Dataset',  # 数据集类型为YOLOv5LVISV1Dataset
                 data_root='data/coco/',  # 数据根目录
                 test_mode=True,  # 测试模式为True
                 ann_file='lvis/lvis_v1_val.json',  # 标注文件路径
                 data_prefix=dict(img=''),  # 数据前缀
                 batch_shapes_cfg=None),  # 批量形状配置为空
    class_text_path='data/captions/lvis_v1_class_captions.json',  # 类别文本路径
    pipeline=test_pipeline)  # 测试管道
val_dataloader = dict(dataset=coco_val_dataset)  # 验证数据加载器设置为coco_val_dataset
test_dataloader = val_dataloader  # 测试数据加载器设置为验证数据加载器
val_evaluator = dict(type='mmdet.LVISMetric',  # 评估器类型为mmdet.LVISMetric
                     ann_file='data/coco/lvis/lvis_v1_val.json',  # 标注文件路径
                     metric=['bbox', 'segm'])  # 评估指标为bbox和segm
test_evaluator = val_evaluator  # 测试评估器设置为验证评估器
find_unused_parameters = True  # 查找未使用的参数为True

.\YOLO-World\demo.py

# 导入必要的库
import argparse
import os.path as osp
from functools import partial
import cv2
import torch
import gradio as gr
import numpy as np
import supervision as sv
from PIL import Image
from torchvision.ops import nms
from mmengine.config import Config, DictAction
from mmengine.runner import Runner
from mmengine.runner.amp import autocast
from mmengine.dataset import Compose
from mmdet.datasets import CocoDataset
from mmyolo.registry import RUNNERS
# 创建边界框标注器和标签标注器对象
BOUNDING_BOX_ANNOTATOR = sv.BoundingBoxAnnotator()
LABEL_ANNOTATOR = sv.LabelAnnotator()
# 解析命令行参数
def parse_args():
    parser = argparse.ArgumentParser(description='YOLO-World Demo')
    parser.add_argument('config', help='test config file path')
    parser.add_argument('checkpoint', help='checkpoint file')
    parser.add_argument(
        '--work-dir',
        help='the directory to save the file containing evaluation metrics')
    parser.add_argument(
        '--cfg-options',
        nargs='+',
        action=DictAction,
        help='override some settings in the used config, the key-value pair '
        'in xxx=yyy format will be merged into config file. If the value to '
        'be overwritten is a list, it should be like key="[a,b]" or key=a,b '
        'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" '
        'Note that the quotation marks are necessary and that no white space '
        'is allowed.')
    args = parser.parse_args()
    return args
# 运行图像处理
def run_image(runner,
              image,
              text,
              max_num_boxes,
              score_thr,
              nms_thr,
              image_path='./work_dirs/demo.png'):
    # 保存图像到指定路径
    image.save(image_path)
    # 将文本分割成列表
    texts = [[t.strip()] for t in text.split(',')] + [[' ']]
    # 构建数据信息字典
    data_info = dict(img_id=0, img_path=image_path, texts=texts)
    # 运行处理管道
    data_info = runner.pipeline(data_info)
    # 构建数据批次
    data_batch = dict(inputs=data_info['inputs'].unsqueeze(0),
                      data_samples=[data_info['data_samples']])
    # 关闭自动混合精度和禁用梯度计算
    with autocast(enabled=False), torch.no_grad():
        # 运行模型的测试步骤,获取输出
        output = runner.model.test_step(data_batch)[0]
        # 获取预测实例
        pred_instances = output.pred_instances
    # 使用非极大值抑制(NMS)筛选预测实例
    keep = nms(pred_instances.bboxes, pred_instances.scores, iou_threshold=nms_thr)
    pred_instances = pred_instances[keep]
    # 根据置信度阈值筛选预测实例
    pred_instances = pred_instances[pred_instances.scores.float() > score_thr]
    # 如果预测实例数量超过最大边界框数目限制
    if len(pred_instances.scores) > max_num_boxes:
        # 保留置信度最高的边界框
        indices = pred_instances.scores.float().topk(max_num_boxes)[1]
        pred_instances = pred_instances[indices]
    # 将预测实例转换为 NumPy 数组
    pred_instances = pred_instances.cpu().numpy()
    # 创建检测结果对象
    detections = sv.Detections(
        xyxy=pred_instances['bboxes'],
        class_id=pred_instances['labels'],
        confidence=pred_instances['scores']
    )
    # 生成标签列表
    labels = [
        f"{texts[class_id][0]} {confidence:0.2f}"
        for class_id, confidence
        in zip(detections.class_id, detections.confidence)
    ]
    # 将图像转换为 NumPy 数组
    image = np.array(image)
    # 将图像从 RGB 转换为 BGR 格式
    image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
    # 在图像上绘制边界框
    image = BOUNDING_BOX_ANNOTATOR.annotate(image, detections)
    # 在图像上添加标签
    image = LABEL_ANNOTATOR.annotate(image, detections, labels=labels)
    # 将图像从 BGR 转换为 RGB 格式
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    # 创建图像对象
    image = Image.fromarray(image)
    # 返回处理后的图像
    return image
def demo(runner, args):
    # 如果当前脚本作为主程序运行
    if __name__ == '__main__':
        # 解析命令行参数
        args = parse_args()
        # 从配置文件加载配置信息
        cfg = Config.fromfile(args.config)
        # 如果有额外的配置选项,则合并到配置中
        if args.cfg_options is not None:
            cfg.merge_from_dict(args.cfg_options)
        # 如果命令行参数中指定了工作目录,则使用该目录,否则使用配置中的工作目录,如果配置中也没有,则使用默认目录
        if args.work_dir is not None:
            cfg.work_dir = args.work_dir
        elif cfg.get('work_dir', None) is None:
            cfg.work_dir = osp.join('./work_dirs', osp.splitext(osp.basename(args.config))[0])
        # 加载模型参数
        cfg.load_from = args.checkpoint
        # 如果配置中没有指定运行器类型,则根据配置创建运行器对象
        if 'runner_type' not in cfg:
            runner = Runner.from_cfg(cfg)
        else:
            # 否则根据配置中的运行器类型创建运行器对象
            runner = RUNNERS.build(cfg)
        # 运行前的钩子函数
        runner.call_hook('before_run')
        # 加载或恢复模型参数
        runner.load_or_resume()
        # 获取测试数据集的数据处理流程
        pipeline = cfg.test_dataloader.dataset.pipeline
        # 创建数据处理流程对象
        runner.pipeline = Compose(pipeline)
        # 设置模型为评估模式
        runner.model.eval()
        # 运行演示
        demo(runner, args)

yolo-world 源码解析(三)(4)https://developer.aliyun.com/article/1483866

相关文章
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
87 2
|
11天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
11天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
11天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
2月前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
57 12
|
30天前
|
PyTorch Shell API
Ascend Extension for PyTorch的源码解析
本文介绍了Ascend对PyTorch代码的适配过程,包括源码下载、编译步骤及常见问题,详细解析了torch-npu编译后的文件结构和三种实现昇腾NPU算子调用的方式:通过torch的register方式、定义算子方式和API重定向映射方式。这对于开发者理解和使用Ascend平台上的PyTorch具有重要指导意义。
|
12天前
|
安全 搜索推荐 数据挖掘
陪玩系统源码开发流程解析,成品陪玩系统源码的优点
我们自主开发的多客陪玩系统源码,整合了市面上主流陪玩APP功能,支持二次开发。该系统适用于线上游戏陪玩、语音视频聊天、心理咨询等场景,提供用户注册管理、陪玩者资料库、预约匹配、实时通讯、支付结算、安全隐私保护、客户服务及数据分析等功能,打造综合性社交平台。随着互联网技术发展,陪玩系统正成为游戏爱好者的新宠,改变游戏体验并带来新的商业模式。
|
2月前
|
存储 安全 Linux
Golang的GMP调度模型与源码解析
【11月更文挑战第11天】GMP 调度模型是 Go 语言运行时系统的核心部分,用于高效管理和调度大量协程(goroutine)。它通过少量的操作系统线程(M)和逻辑处理器(P)来调度大量的轻量级协程(G),从而实现高性能的并发处理。GMP 模型通过本地队列和全局队列来减少锁竞争,提高调度效率。在 Go 源码中,`runtime.h` 文件定义了关键数据结构,`schedule()` 和 `findrunnable()` 函数实现了核心调度逻辑。通过深入研究 GMP 模型,可以更好地理解 Go 语言的并发机制。
|
2月前
|
消息中间件 缓存 安全
Future与FutureTask源码解析,接口阻塞问题及解决方案
【11月更文挑战第5天】在Java开发中,多线程编程是提高系统并发性能和资源利用率的重要手段。然而,多线程编程也带来了诸如线程安全、死锁、接口阻塞等一系列复杂问题。本文将深度剖析多线程优化技巧、Future与FutureTask的源码、接口阻塞问题及解决方案,并通过具体业务场景和Java代码示例进行实战演示。
61 3
|
3月前
|
存储
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
`HashMap`的`put`方法通过调用`putVal`实现,主要涉及两个场景下的扩容操作:1. 初始化时,链表数组的初始容量设为16,阈值设为12;2. 当存储的元素个数超过阈值时,链表数组的容量和阈值均翻倍。`putVal`方法处理键值对的插入,包括链表和红黑树的转换,确保高效的数据存取。
68 5

推荐镜像

更多