MyBatis-Plus 全方位深度指南:从入门到精通

news/2025/9/22 17:46:59/文章来源:https://www.cnblogs.com/yongjannes/p/19105704

在 Java 的世界里,数据持久化是任何企业级应用的基石。MyBatis 以其轻量、灵活以及对 SQL 的完全掌控而备受开发者喜爱。然而,随着项目复杂度的增加,开发者们发现自己陷入了编写大量重复性 CRUD(创建、读取、更新、删除)代码的泥潭,这不仅枯燥,也容易出错。

为了将开发者从这些重复劳动中解放出来,MyBatis-Plus (简称 MP) 应运而生。它并非要取代 MyBatis,而是作为其最强大的“增强套件”,在完全兼容 MyBatis 的前提下,提供了海量的便捷功能,其核心目标只有一个:为简化开发、提高效率而生

本指南将带您从零开始,一步步探索并掌握这个强大的工具。

第一章:初识 MyBatis-Plus

1.1 为什么选择 MyBatis-Plus?

在引入任何新技术之前,我们都应该问“为什么”。选择 MP 的理由非常充分:

  • 无侵入性:MP 只是 MyBatis 的一个增强工具,不会对您现有的 MyBatis 项目造成任何影响。您可以随时引入,并与原生功能混合使用。
  • 代码极简:对于单表的增删改查,您不再需要编写任何 XML SQL 语句。MP 已经通过内置的 BaseMapper 为您准备好了一切。
  • 功能强大:除了基础 CRUD,MP 还内置了分页、逻辑删除、乐观锁、自动填充、性能分析等一系列企业级开发所需的高级功能。
  • 类型安全:其独创的 LambdaQueryWrapper 让您告别手写字段名的时代,通过方法引用构建查询条件,安全且易于重构。
  • 生态完善:拥有活跃的社区和清晰的官方文档,遇到问题可以快速找到解决方案。

1.2 核心理念

MP 的设计哲学可以总结为“约定优于配置”。它假设了一些通用开发场景(例如,主键名为 id,逻辑删除字段为 deleted),并提供了默认实现。您只需遵循这些约定,就能以极少的代码量完成大量工作。当然,所有约定都是可以自定义配置的。

第二章:扬帆起航 - 环境搭建

让我们通过一个标准的 Spring Boot 项目来快速搭建 MyBatis-Plus 环境。

2.1 添加项目依赖

在您的 Maven 项目的 pom.xml 文件中,加入 mybatis-plus-boot-starter 依赖。它会自动管理 MyBatis 和 JDBC 的相关依赖。

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.12</version>
</dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope>
</dependency>

2.2 配置数据源

在 Spring Boot 的核心配置文件 application.yml 中,配置您的数据库连接信息。

spring:datasource:url: jdbc:mysql://127.0.0.1:3306/your_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword: your_passworddriver-class-name: com.mysql.cj.jdbc.Driver

2.3 扫描 Mapper 接口

最后,在您的 Spring Boot 启动类上,使用 @MapperScan 注解来告诉 MP 您的 Mapper 接口存放在哪个包下。

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.yourcompany.project.mapper") // 替换为您的 Mapper 包路径
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

至此,您的项目已经成功集成了 MyBatis-Plus!

第三章:核心构件 - 实体、Mapper 与 Service

MP 的代码主要围绕这三个核心组件展开。

3.1 实体类 (Entity) 与注解

实体类是数据库表在 Java 代码中的映射。MP 提供了一系列注解来精确描述这种映射关系。

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;@Data
@TableName("sys_user") // 映射数据库中的 `sys_user` 表
public class User {// @TableId:定义主键// value = "user_id": 数据库主键字段名为 `user_id`// type = IdType.AUTO: 主键策略为数据库自增@TableId(value = "user_id", type = IdType.AUTO)private Long id;// @TableField:定义普通字段// value = "user_name": 数据库字段名为 `user_name`// (如果属性名符合驼峰转下划线规则,如 `userName` -> `user_name`,此注解可省略)@TableField("user_name")private String name;private Integer age;private String email;// @TableField(exist = false):表示该字段在数据库表中不存在,仅为业务逻辑需要@TableField(exist = false)private String gender;
}

常用主键策略 (IdType)

  • AUTO: 数据库 ID 自增。
  • ASSIGN_ID: 雪花算法生成分布式唯一 ID (长整型或字符串)。
  • INPUT: 用户手动输入。

3.2 Mapper 接口

您只需让您的 Mapper 接口继承 BaseMapper<T>,便可瞬间拥有强大的 CRUD 能力。

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yourcompany.project.entity.User;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserMapper extends BaseMapper<User> {// 没错,就是这么空!// 所有的基础增、删、改、查、分页查询方法都已经由 BaseMapper 提供了。// 如果您有复杂的多表查询需求,仍然可以像原生 MyBatis 一样在这里定义方法,并编写 XML。
}

3.3 Service 层(最佳实践)

为了更好地进行业务逻辑封装和事务控制,官方强烈推荐使用 Service 层。MP 也为此提供了便利。

  1. IService 接口

    import com.baomidou.mybatisplus.extension.service.IService;
    import com.yourcompany.project.entity.User;public interface UserService extends IService<User> {// 定义您自己的业务方法
    }
    
  2. ServiceImpl 实现

    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.yourcompany.project.entity.User;
    import com.yourcompany.project.mapper.UserMapper;
    import org.springframework.stereotype.Service;@Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {// ServiceImpl 已经帮您注入了 UserMapper,并实现了 IService 的所有方法。// 您可以直接调用如 save(), list(), page() 等便捷方法。
    }
    

第四章:灵魂所在 - 条件构造器 Wrapper

当简单的 CRUD 无法满足复杂的查询需求时,Wrapper 便闪亮登场。它允许您以编程的方式,安全、直观地构建复杂的 WHERE 查询条件。

核心建议:始终使用 LambdaQueryWrapper,它能提供编译期类型安全检查,让您的代码更健壮。

4.1 核心查询方法详解

方法 含义 生成 SQL 示例
.eq(User::getName, "张三") 等于 (Equal) name = '张三'
.ne(User::getStatus, 0) 不等于 (Not Equal) status <> 0
.gt(User::getAge, 18) 大于 (Greater Than) age > 18
.ge(User::getAge, 18) 大于等于 (Greater Equal) age >= 18
.lt(User::getAge, 60) 小于 (Less Than) age < 60
.le(User::getAge, 60) 小于等于 (Less Equal) age <= 60
.between(User::getAge, 20, 30) 在...之间 age BETWEEN 20 AND 30
.like(User::getName, "王") 包含 (LIKE '%王%') name LIKE '%王%'
.likeLeft(User::getEmail, "@qq.com") 左模糊 (LIKE '%@qq.com') email LIKE '%@qq.com'
.likeRight(User::getName, "李") 右模糊 (LIKE '李%') name LIKE '李%'
.isNull(User::getManagerId) 为 NULL manager_id IS NULL
.isNotNull(User::getEmail) 不为 NULL email IS NOT NULL
.in(User::getId, 1, 2, 3) 在集合中 id IN (1, 2, 3)
.orderByAsc(User::getAge) 升序排序 ORDER BY age ASC
.orderByDesc(User::getCreateTime) 降序排序 ORDER BY create_time DESC

4.2 实战演练

需求:查询名字以 "李" 开头、年龄在 20 到 40 岁之间、且邮箱不为空的用户,结果按年龄降序排列。

@Autowired
private UserService userService;public List<User> findUsers() {LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.likeRight(User::getName, "李").between(User::getAge, 20, 40).isNotNull(User::getEmail).orderByDesc(User::getAge);return userService.list(wrapper);
}

这段代码清晰地表达了业务逻辑,并且完全避免了手写 SQL 可能带来的注入风险和拼写错误。

4.3 更新专用:UpdateWrapper

当您需要更新部分字段时,可以使用 LambdaUpdateWrapper

需求:将所有名字为 "张三" 的用户的年龄更新为 30 岁。

LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(User::getName, "张三")       // WHERE 条件.set(User::getAge, 30);        // SET 子句boolean success = userService.update(updateWrapper);

生成 SQL: UPDATE sys_user SET age = 30 WHERE user_name = '张三'

第五章:企业级高级特性

要启用以下大部分功能,您需要配置一个 MybatisPlusInterceptor 拦截器。

@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 1. 添加分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));// 2. 添加乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}

5.1 物理分页

配置分页插件后,分页查询变得异常简单。

Java

// 构建分页参数:查询第 1 页,每页 10 条
Page<User> page = new Page<>(1, 10);// 构建查询条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 18);// 执行分页查询
Page<User> resultPage = userService.page(page, wrapper);System.out.println("总记录数: " + resultPage.getTotal());
System.out.println("当前页数据: " + resultPage.getRecords());

5.2 逻辑删除

在实际业务中,我们通常不会物理删除数据库中的记录,以便于数据审计、追踪或恢复。这种只通过一个字段来标记数据为“已删除”状态的操作,被称为“逻辑删除”或“软删除”。MyBatis-Plus 对此提供了极其优雅和透明的支持。

第一步:在实体类中指定逻辑删除字段

要启用逻辑删除,首先您需要在实体类中代表“删除状态”的字段上添加 @TableLogic 注解。MP 会识别这个注解,并对相关操作进行特殊处理。

import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;@Data
public class User {private Long id;private String name;// @TableLogic 是启用逻辑删除的关键@TableLogicprivate Integer deleted; 
}

第二步:在 application.yml 中配置全局默认值(可选但推荐)

为了让逻辑删除的行为更加清晰和统一,推荐在 application.yml 中配置全局的“已删除”和“未删除”状态值。

mybatis-plus:global-config:db-config:# 逻辑删除字段名logic-delete-field: deleted# 逻辑已删除值(默认为 1)logic-delete-value: 1# 逻辑未删除值(默认为 0)logic-not-delete-value: 0
  • logic-delete-value: 1:定义了当执行删除操作时,@TableLogic 标记的字段值会被更新为 1
  • logic-not-delete-value: 0:定义了当执行查询操作时,会自动附加条件,只查询 deleted 字段值为 0 的记录。

功能效果演示

完成上述配置后,逻辑删除对您的业务代码是完全透明的,您仍然像以前一样调用方法,但底层的 SQL 已经发生了改变。

1. 执行删除操作

您的业务代码:

// 表面上是调用删除方法
userService.removeById(101L); 

MyBatis-Plus 实际执行的 SQL:

UPDATE user SET deleted=1 WHERE id=101 AND deleted=0;

解析: DELETE 操作被自动拦截并转换为 UPDATE 操作。它会将 deleted 字段的值从 0(未删除)更新为 1(已删除),并且 WHERE 子句中自动加入了 deleted=0,确保了操作的幂等性。

2. 执行查询操作

您的业务代码:

// 表面上是调用一个普通的查询方法
User user = userService.getById(101L);

MyBatis-Plus 实际执行的 SQL:

SELECT id, name, deleted FROM user WHERE id=101 AND deleted=0;

解析: 任何查询(包括 Wrapper 构建的复杂查询)都会被自动在 WHERE 子句末尾追加 AND deleted=0 条件。这保证了您的业务代码在任何时候获取到的都是“有效”数据,无需手动在每个查询中添加此条件,极大简化了代码并降低了出错的风险。

5.3 乐观锁

用于解决高并发下的数据更新冲突问题。

  1. 数据库表增加 version 字段 (通常是 INTBIGINT)。

  2. 在实体类对应字段上添加 @Version 注解。

    @Version
    private Integer version;
    
  3. 配置 OptimisticLockerInnerInterceptor 拦截器。

当您执行更新时,MP 会自动检查并递增 version 字段,确保您是基于最新数据进行的修改。

5.4 自动填充公共字段

在大多数业务表中,create_timeupdate_time 这两个字段几乎是标配。我们希望在新增记录时自动填充创建和更新时间,在更新记录时自动更新时间,而无需在业务代码中手动设置。MP 的自动填充功能完美解决了这个问题。

第一步:实现 MetaObjectHandler 接口

创建一个类并实现 MetaObjectHandler 接口,重写 insertFillupdateFill 方法。通过 @Component 注解将其注册为 Spring Bean。

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {// 插入时,同时填充创建时间和更新时间this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}@Overridepublic void updateFill(MetaObject metaObject) {// 更新时,只填充更新时间this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}
}

第二步:在实体类字段上添加注解

在需要自动填充的实体类字段上,使用 @TableField 注解并指定 fill 策略。

@Data
public class User {// ... 其他字段// 字段添加填充内容@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;
}
  • FieldFill.INSERT: 只在插入时填充。
  • FieldFill.UPDATE: 只在更新时填充。
  • FieldFill.INSERT_UPDATE: 插入和更新时都填充。

完成这两步后,您在执行 save(user)updateById(user) 等操作时,MP 将会自动调用 MyMetaObjectHandler 中的逻辑,为相应字段赋值。

第六章:效率神器 - 代码生成器

当开始一个新项目或新模块时,需要创建大量结构相似的 Entity、Mapper、Service、Controller 代码。MyBatis-Plus 提供了强大的代码生成器(AutoGenerator),可以连接数据库,一键生成这些基础代码,极大提升开发效率。

第一步:添加生成器依赖

pom.xml 中添加 mybatis-plus-generator 的依赖。

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.7</version>
</dependency>
<dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.3</version>
</dependency>

第二步:编写并执行生成代码

创建一个简单的 main 方法来配置和执行代码生成。

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import java.util.Collections;public class CodeGenerator {public static void main(String[] args) {FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/your_db", "root", "your_password").globalConfig(builder -> {builder.author("YourName") // 设置作者.outputDir(System.getProperty("user.dir") + "/src/main/java"); // 指定输出目录}).packageConfig(builder -> {builder.parent("com.yourcompany.project") // 设置父包名.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/mapper")); // 设置 XML 生成路径}).strategyConfig(builder -> {builder.addInclude("sys_user", "sys_role") // 设置需要生成的表名.addTablePrefix("sys_"); // 设置过滤表前缀}).templateEngine(new VelocityTemplateEngine()) // 使用 Velocity 引擎模板.execute();}
}

配置解析:

  • FastAutoGenerator.create(): 配置数据库连接信息。
  • .globalConfig(): 配置全局选项,如作者、输出路径等。
  • .packageConfig(): 配置包名信息,以及各类文件(如XML)的单独输出路径。
  • .strategyConfig(): 策略配置,是最核心的配置。可以指定要生成的表、要忽略的表前缀、Entity/Controller/Service/Mapper 的各种生成策略等。

运行这个 main 方法,您项目对应的包下就会立即生成 sys_usersys_role 两张表的所有后端基础代码。

第七章:灵活性 - 与原生 XML 共存

当遇到极其复杂的报表查询或多表 JOIN 时,Wrapper 可能不够用。此时,您可以无缝地回归 MyBatis 的原生 XML 方式。

  1. UserMapper 接口中定义方法:

    List<UserVo> getUserDetailList(@Param("status") Integer status);
    
  2. resources/mapper/UserMapper.xml 中编写 SQL:

    <select id="getUserDetailList" resultType="com.yourcompany.project.vo.UserVo">SELECT u.user_name, d.dept_nameFROM sys_user uLEFT JOIN sys_dept d ON u.dept_id = d.idWHERE u.status = #{status}
    </select>
    

MP 的通用方法和您的自定义 XML 方法可以和谐共存,提供了极致的灵活性。

结语

MyBatis-Plus 通过一系列精心设计的功能,极大地简化了 Java 持久层的开发,将开发者从繁重的 CRUD 中解放出来。它易于上手,功能强大,同时又不失 MyBatis 原生的灵活性。

最佳实践回顾:

  • 优先使用 Service 层:将业务逻辑封装在 ServiceImpl 中,而不是直接操作 Mapper
  • 拥抱 LambdaWrapper:为了代码的类型安全和可维护性,始终使用 LambdaQueryWrapperLambdaUpdateWrapper
  • 善用高级特性:针对分页、逻辑删除、并发控制等常见场景,积极使用 MP 提供的成熟解决方案。
  • 启动项目时利用代码生成器:在新项目或模块开始时,首先使用代码生成器构建基础骨架。

无论您是正在开始一个新项目,还是希望优化现有项目的开发效率,MyBatis-Plus 都绝对是您技术栈中值得拥有的利器。掌握它,意味着您可以用更少的代码,实现更强大的功能,从而更专注于创造性的业务逻辑开发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909865.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Stm32学习过程笔记

View PostStm32学习过程笔记标准库 1.RCC时钟设置(必备) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//APB2外设2. GPIO外设通用输入输出 GPIO_InitTypeDef GPIO_InitStructure; …

鸿蒙项目实战(十):web和js交互

1、实现android的addJavascriptInterface操作 即鸿蒙注入JavaScript对象到window对象中 javaScriptProxy javaScriptProxy(javaScriptProxy: JavaScriptProxy) // xxx.ets import { webview } from @kit.ArkWeb;class …

【9.24 直播】集群数据管理实战:时序数据库 IoTDB 数据分区、同步与备份详解

保障集群高性能、高可用与数据安全,9.24 19 点线上见!📁分布式高可用场景下,如何设计数据分区策略才能最大化系统效能? 🚀跨“端-边-云”数据同步如何保证一致性与可靠性? 🔍数据备份方案又该如何设计才能万…

影视广告制作报价单宁波seo推广开发

【电脑商网专稿】虚拟软件究竟是什么软件, 是让所有的软件都”虚拟”执行吗, 虚拟软件层究竟是怎样的一层软件? 为什么现在这么多的公司和个人都在使用这种软件, 虚拟软件能代替操作系统完全控制硬件吗? 下面就让我们逐渐的揭开虚拟化技术这一特殊软件层的秘密吧.谈到虚拟化就…

函数计算进化之路:AI 应用运行时的状态剖析

将 AI 应用运行时迁移至 Serverless 平台,是应对未来智能化浪潮、实现敏捷创新和高效运营的必由之路。作者:世如 AI 应用基础设施正在经历一场深刻的范式迁移。传统的 AI 应用工作负载部署模式,以其长期预置、“始终…

自己做网站 服务器数字展厅企业展厅

最近推送了几个Excel中最难的函数&#xff0c;哀嚎遍野&#xff0c;太难了……所以今天我们来“从万丈高楼平地起”的平地讲起&#xff01;搞懂Excel单元格引用方式&#xff0c;是保证公式准确最最基本的条件&#xff01;单元格引用方式整体分三种&#xff1a;相对引用(A1)绝对…

发布网站搭建教程平面设计作品集如何制作

Tkinter标准库 Tkinter是Python的标准GUI库&#xff0c;也是最常用的Python GUI库之一&#xff0c;提供了丰富的组件和功能&#xff0c;包括窗口、按钮、标签、文本框、列表框、滚动条、画布、菜单等&#xff0c;方便开发者进行图形界面的开发。Tkinter库基于Tk for Unix/Wind…

宁波建设局网站做水果代理去哪个网站

设计思想 傅里叶变换&#xff0c;表示能将满足一定条件的某个函数表示成三角函数&#xff08;正弦和/或余弦函数&#xff09;或者它们的积分的线性组合。在不同的研究领域&#xff0c;傅里叶变换具有多种不同的变体形式&#xff0c;如连续傅里叶变换和离散傅里叶变换。 快速傅…

自动全屏网站模板wordpress Apache升级

概述 之前在《【Godot4.2】Tree控件自定义树形数据ETD及其解析》一文中&#xff0c;实现了对带缩进的层级结构文本的解析&#xff0c;并将其用于Tree控件的列表项构造。 不过当时并没有实现专门的类&#xff0c;今天花了一点时间实现了一下。现在可以更方便的构造和解析ETD数…

利鑫做彩票网站网站规划与设计h5

一. 安全编程 rust逆向&#xff0c;直接动调 定位关键函数sub_7FD043E88C70 下断点跟进 观察控制台 guess number plz input 1-10 number 这时我们随便输入一个数&#xff0c;往下跟进 .text:00007F14B3684E9B .text:00007F14B3684E9B loc_7F14B3684E9B: .text:00007F14B…

网站免费下载安装大全手机版国外做名片网站

Android中提供的HttpURLConnection和HttpClient接口可以用来开发HTTP程序。以下是本人在学习中的总结与归纳。1. HttpURLConnection接口 首先需要明确的是&#xff0c;Http通信中的POST和GET请求方式的不同。GET可以获得静态页面&#xff0c;也可以把参数放在URL字符串后面&…

广州魔站建站企业网站实施方案

嵌入式的坑烧钱嵌入式的学习十分烧钱&#xff0c;这就让人有点望而却步。我是做DSP起步的&#xff0c;更是能体会到嵌入式绝对是一个拿钱搭梯子的学习行业。在我的学习过程中身边有不少的人投向了CS行业&#xff0c;也就是纯软件开发&#xff0c;比如网页、手机应用、数据库等。…

公司网站本地如何弄中卫市建设网站

计算机考研学院简介计算机与通信学院前身为原湖南大学计算机科学系。1978年组建计算机教研室并开办计算机本科专业&#xff0c;1981年5月正式成立计算科学系&#xff0c;2001年10月正式成立计算机与通信学院。学院现有计算机应用技术博士授权点&#xff1b;计算机科学与技术、信…

01_进程与线程

大部分操作系统的任务调度是采用时间片轮转的抢占式调度方式,也就是说一个任务执行一小段时间后强制暂停去执行下一个任务,每个任务轮流执行。任务执行的一小段时间叫做时间片,任务正在执行时的状态叫运行状态,任务…

第六届医学人工智能国际学术会议(ISAIMS 2025)

第六届医学人工智能国际学术会议(ISAIMS 2025) 2025 6th International Symposium on Artificial Intelligence for Medical Sciences ( ISAIMS 2025) 第六届医学人工智能国际学术会议(ISAIMS 2025)将于2025年10月24…

完整教程:Java多线程初阶

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

网站查询服务器成都网站建设公

战神4 幕后花絮 概念艺术找出Java幕后发生的事情&#xff0c;以及新功能如何实现 在上一篇文章中&#xff0c;我们介绍了即将发布的Java 9版本的新功能和尚待解决的功能&#xff0c;并简要提到了将新功能添加到下一个版本之前要经历的过程。 由于此过程几乎影响了所有Java开发人…

redis 6.0 多线程

Redis 6.0 的多线程,并非指命令处理逻辑的多线程(命令执行仍然是单线程的),而是特指网络 I/O 的多线程,其核心目标是优化大量网络 I/O 带来的性能瓶颈,提升吞吐量,尤其是在高并发场景下。Redis 6.0 之前 - 单线…

docker 常用命令与端口映射

搜索镜像:从 Docker Hub 查找镜像docker search <镜像名称> # 例如:docker search nginx拉取镜像:从仓库下载镜像到本地docker pull <镜像名称:标签> # 例如:docker pull nginx:latest # 如果不写标签…

衡阳市住房建设局网站软装设计ppt

好的思维导图软件能帮助用户更好的发挥创作能力&#xff0c;XMind是一款流行的思维导图软件&#xff0c;可以帮助用户创建各种类型的思维导图和概念图。 多样化的导图类型&#xff1a;XMind提供了多种类型的导图&#xff0c;如鱼骨图、树形图、机构图等&#xff0c;可以满足不同…