4.Executor执行器

article/2025/9/9 2:32:54

1.Executor 主体结构

Executor是MyBatis执行者接口,执行器的功能包括:

  • 基本功能:改、查,没有增删的原因是,所有的增删操作都可以归结到改。
  • 缓存维护:这里的缓存主要是为一级缓存服务,功能包括创建缓存Key、清理缓存、判断缓存是否存在。
  • 事物管理:提交、回滚、关闭、批处理刷新。

Executor 的生命周期和 SqlSession 是一样的,之所以要明确的指出这一点是因为 Executor 中包含了缓存的处理,并且因为 SqlSession 是线程不安全的。

对于这个接口MyBatis是有三个实现子类。分别是

  • SimpleExecutor(简单执行器)

  • ReuseExecutor(重用执行器)

  • BatchExecutor(批处理执行器)。

    public interface Executor {ResultHandler NO_RESULT_HANDLER = null;int update(MappedStatement ms, Object parameter) throws SQLException;<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;<E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;List<BatchResult> flushStatements() throws SQLException;void commit(boolean required) throws SQLException;void rollback(boolean required) throws SQLException;CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);boolean isCached(MappedStatement ms, CacheKey key);void clearLocalCache();void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);Transaction getTransaction();void close(boolean forceRollback);boolean isClosed();void setExecutorWrapper(Executor executor);}
    

1.1Executor类结构

image-20210801222434052

其各自的功能:

  • BaseExecutor:基础执行器,封装了子类的公共方法,包括一级缓存、延迟加载、回滚、关闭等功能;
  • SimpleExecutor:简单执行器,每执行一条 sql,都会打开一个 Statement,执行完成后关闭;
  • ReuseExecutor:重用执行器,相较于 SimpleExecutor 多了 Statement 的缓存功能,并使用SQL语句作为Key,其内部维护一个 Map<String, Statement>,每次编译完成的 Statement 都会进行缓存,不会关闭;
  • BatchExecutor:批量执行器,基于 JDBC 的 addBatch、executeBatch 功能,并且在当前 sql 和上一条 sql 完全一样的时候,重用 Statement,在调用 doFlushStatements 的时候,将数据刷新到数据库;
  • CachingExecutor:缓存执行器,装饰器模式,在开启二级缓存的时候。会在上面三种执行器的外面包上 CachingExecutor;

1.2创建Executor

Executor会根据ExecutorType的类型进行创建,如果mybatis的config配置文件开启了二级缓存(cacheEnabled=true)则会使用装饰器模式创建一个CachingExecutor来维护二级缓存。后面会详细介绍

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {executorType = executorType == null ? defaultExecutorType : executorType;executorType = executorType == null ? ExecutorType.SIMPLE : executorType;Executor executor;if (ExecutorType.BATCH == executorType) {executor = new BatchExecutor(this, transaction);} else if (ExecutorType.REUSE == executorType) {executor = new ReuseExecutor(this, transaction);} else {executor = new SimpleExecutor(this, transaction);}// 开启二级缓存,使用装饰器模式if (cacheEnabled) {executor = new CachingExecutor(executor);}// mybatis插件相关  executor = (Executor) interceptorChain.pluginAll(executor);return executor;
}

2.BaseExecutor

BaseExecutor 基础执行器主要是用于维护一级缓存和事物。事物是通过会话中调用commit、rollback进行管理。

重点在于一级缓存这块它是如何处理的?

它实现了Executor中的Query与update方法。SqlSession会话中SQL请求,正是调用的这两个方法。Query方法中处理一级缓存逻辑,即根据SQL及参数判断缓存中是否存在数据,有就走缓存。否则就会调用子类的doQuery() 方法去查询数据库,然后在设置缓存。在doUpdate() 中主要是用于清空缓存。

image-20210801225742819

2.1query

public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {// 获取绑定的sqlBoundSql boundSql = ms.getBoundSql(parameter);// 缓存key  CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());if (closed) {throw new ExecutorException("Executor was closed.");}// mapperxml文件FlushCache 配置为true,会清除缓存。不使用缓存if (queryStack == 0 && ms.isFlushCacheRequired()) {clearLocalCache();}List<E> list;try {queryStack++;// 首先查看一级缓存list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;if (list != null) {handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);} else {// 没有查到的时候直接到数据库查找  list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);}} finally {queryStack--;}if (queryStack == 0) {for (DeferredLoad deferredLoad : deferredLoads) {deferredLoad.load();}// issue #601deferredLoads.clear();// 一级缓存本身不能关闭  // mybatis-config的setting节点设置一级缓存LocalCacheScope为STATEMENT也会清除缓存// <setting name="localCacheScope" value="STATEMENT"/>  if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {// issue #482clearLocalCache();}}return list;
}
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {List<E> list;localCache.putObject(key, EXECUTION_PLACEHOLDER);try {// 真正的去数据库查询数据  list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);} finally {// 先清除缓存  localCache.removeObject(key);}// 查询结果加入到缓存中  localCache.putObject(key, list);if (ms.getStatementType() == StatementType.CALLABLE) {localOutputParameterCache.putObject(key, parameter);}return list;
}

2.2查询

public int update(MappedStatement ms, Object parameter) throws SQLException {ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());if (closed) {throw new ExecutorException("Executor was closed.");}// 清除缓存  clearLocalCache();return doUpdate(ms, parameter);
}

2.3模板方法

这里就是一个典型的模版方法模式了,子类都会实现自己模版方法;

protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;protected abstract List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException;protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)throws SQLException;protected abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)throws SQLException;

2.4事务相关

@Override
public void close(boolean forceRollback) {try {try {// close之前,先回滚事务。// connection没有设置自动提交,新增数据后没有commit。连接close之前,需要把数据回滚掉  rollback(forceRollback);} finally {if (transaction != null) {transaction.close();}}} catch (SQLException e) {// Ignore. There's nothing that can be done at this point.log.warn("Unexpected exception on closing transaction.  Cause: " + e);} finally {transaction = null;deferredLoads = null;localCache = null;localOutputParameterCache = null;closed = true;}
}public void commit(boolean required) throws SQLException {if (closed) {throw new ExecutorException("Cannot commit, transaction is already closed");}// 提交会清除一级缓存及刷新StatementsclearLocalCache();flushStatements();if (required) {transaction.commit();}}@Overridepublic void rollback(boolean required) throws SQLException {if (!closed) {try {// 回滚会清除一级缓存及刷新Statements  clearLocalCache();flushStatements(true);} finally {if (required) {transaction.rollback();}}}}

3.SimpleExecutor

SimpleExecutor是默认执行器,它的行为是每处理一次会话当中的SQl请求都会通过对应的StatementHandler 构建一个新个Statement,这就会导致即使是相同SQL语句也无法重用Statement。每次打开一个 Statement,使用完成以后关闭。后续的处理交由StatementHandler进行增删改查

@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {Statement stmt = null;try {Configuration configuration = ms.getConfiguration();// 构建StatementHandlerStatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);// 构建新的Statementstmt = prepareStatement(handler, ms.getStatementLog());return handler.update(stmt);} finally {// 关闭Statement,同JDBC经典用法  closeStatement(stmt);}
}@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {Statement stmt = null;try {Configuration configuration = ms.getConfiguration();StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);stmt = prepareStatement(handler, ms.getStatementLog());return handler.query(stmt, resultHandler);} finally {closeStatement(stmt);}
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {Statement stmt;// 获取连接,在Baseexecutor中,从Transaction中获取Connection connection = getConnection(statementLog);stmt = handler.prepare(connection, transaction.getTimeout());handler.parameterize(stmt);return stmt;
}

4.ReuseExecutor

ReuseExecutor 区别在于他会将在会话期间内的Statement进行缓存,并使用SQL语句作为Key。所以当执行下一请求的时候,不在重复构建Statement,而是从缓存中取出并设置参数,然后执行。

这也说明为啥执行器不能跨线程调用,这会导致两个线程给同一个Statement 设置不同场景参数。

// 缓存Statement的Map
private final Map<String, Statement> statementMap = new HashMap<>();private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {Statement stmt;// 获取绑定的sql  BoundSql boundSql = handler.getBoundSql();String sql = boundSql.getSql();// 如果缓存中已经有了,直接得到Statement  if (hasStatementFor(sql)) {// 从缓存中获取Statementstmt = getStatement(sql);applyTransactionTimeout(stmt);} else {// 如果缓存没有,就编译一个然后加入缓存Connection connection = getConnection(statementLog);stmt = handler.prepare(connection, transaction.getTimeout());// 放入缓存中,下次使用  putStatement(sql, stmt);}handler.parameterize(stmt);return stmt;
}private boolean hasStatementFor(String sql) {try {Statement statement = statementMap.get(sql);// 缓存Statement存在且连接Connection没有关闭return statement != null && !statement.getConnection().isClosed();} catch (SQLException e) {return false;}
}

发现ReuseExecutor没有去手动关闭closeStatement。当没有设置connection为自动提交时,我们需要手动commit,close,rollback。会间接调用doFlushStatements来关闭Statements。

如果设置connection为AutoCommit时,我们需要自己调用doFlushStatements来关闭Statements。

public List<BatchResult> doFlushStatements(boolean isRollback) {for (Statement stmt : statementMap.values()) {closeStatement(stmt);}statementMap.clear();return Collections.emptyList();
}

5.BatchExecutor

BatchExecutor 顾名思议,它就是用来作批处理的。但会将所 有SQL请求集中起来,最后调用Executor.flushStatements() 方法时一次性将所有请求发送至数据库。

BachExecutor 是基于 JDBC 的 addBatch、executeBatch 功能的执行器,所以 BachExecutor 只能用于更新(insert|delete|update),不能用于查询(select)。doQuery与SimpleExecutor一致。

// 待处理的 Statement
private final List<Statement> statementList = new ArrayList<>();
// 对应的结果集
private final List<BatchResult> batchResultList = new ArrayList<>();
// 上一次执行 sql
private String currentSql;
// 上次执行的 MappedStatement
private MappedStatement currentStatement;public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {final Configuration configuration = ms.getConfiguration();final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);final BoundSql boundSql = handler.getBoundSql();// 本次执行的 sqlfinal String sql = boundSql.getSql();final Statement stmt;// 当本次执行的 sql 和 MappedStatement 与上次的相同时,直接复用上一次的 Statementif (sql.equals(currentSql) && ms.equals(currentStatement)) {int last = statementList.size() - 1;stmt = statementList.get(last);applyTransactionTimeout(stmt);handler.parameterize(stmt);// fix Issues 322BatchResult batchResult = batchResultList.get(last);batchResult.addParameterObject(parameterObject);} else {// 不同时,新建 Statement,并加入缓存Connection connection = getConnection(ms.getStatementLog());stmt = handler.prepare(connection, transaction.getTimeout());handler.parameterize(stmt);    // fix Issues 322currentSql = sql;currentStatement = ms;statementList.add(stmt);batchResultList.add(new BatchResult(ms, sql, parameterObject));}// 添加批处理任务handler.batch(stmt);// 注意这里返回的不再是更新的行数,而是一个常量return BATCH_UPDATE_RETURN_VALUE;
}

数据什么更新到数据库呢?

处理 update 的任何操作,包括 commit、close等任何操作,具体执行的方法就是 doFlushStatements此外需要注意的是 Batch 方式插入使用 useGeneratedKeys 获取主键,在提交完任务之后,并不能马上取到,因为此时 sql 语句还在缓存中没有真正执行,当执行完 Flush 之后,会通过回调的方式反射设置主键;

public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {try {List<BatchResult> results = new ArrayList<>();if (isRollback) {return Collections.emptyList();}// 循环处理statement的executeBatchfor (int i = 0, n = statementList.size(); i < n; i++) {Statement stmt = statementList.get(i);applyTransactionTimeout(stmt);BatchResult batchResult = batchResultList.get(i);try {// 更新影响的结果数batchResult.setUpdateCounts(stmt.executeBatch());MappedStatement ms = batchResult.getMappedStatement();List<Object> parameterObjects = batchResult.getParameterObjects();KeyGenerator keyGenerator = ms.getKeyGenerator();// insert返回主键,设置进实体对象中。会单独分析if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) {Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator;jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects);} else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { //issue #141for (Object parameter : parameterObjects) {keyGenerator.processAfter(this, ms, stmt, parameter);}}// Close statement to close cursor #1109// 处理结束后关闭statementcloseStatement(stmt);} catch (BatchUpdateException e) {StringBuilder message = new StringBuilder();message.append(batchResult.getMappedStatement().getId()).append(" (batch index #").append(i + 1).append(")").append(" failed.");if (i > 0) {message.append(" ").append(i).append(" prior sub executor(s) completed successfully, but will be rolled back.");}throw new BatchExecutorException(message.toString(), e, results, batchResult);}results.add(batchResult);}// 返回处理结果,从BatchResult.updateCounts 获取更新的条数return results;} finally {for (Statement stmt : statementList) {closeStatement(stmt);}currentSql = null;statementList.clear();batchResultList.clear();}}

只有连续相同的SQL语句并且相同的SQL映射声明,才会重用Statement,并利用其批处理功能。否则会构建一个新的Satement然后在flushStatements() 时一次执行。这么做的原因是它要保证执行顺序,跟调用顺序一至。

image-20210802004347876

假设上图中相同的线条颜色,就是相同的SQL语句。为了保证执行顺序只有绿色线条合并成一个Statement而两条黄线不能,否则就会导致,后面的黄线先于中间的绿线执行,有违调用顺序。这中情况会创建3个Satement,两天sql语句之间有 其他的sql语句。

6.CachingExecutor

CachingExecutor缓存执行器,用于处理二级缓存的。二级缓存和一级缓存相对独立的逻辑,而且二级缓存可以通过参数控制关闭,而一级缓存是不可以的。综上原因把二级缓存单独抽出来处理。抽取的方式采用了装饰者设计模式,即在CachingExecutor 对原有的执行器进行包装,处理完二级缓存逻辑之后,把SQL执行相关的逻辑交给实至的Executor处理。

image-20210802235146269

7.执行器总结

执行器的种类有:基础执行器、简单执行器、重用执行器和批处理执行器,此外通过装饰器形式添加了一个缓存执行器。对应功能包括缓存处理、事物处理、重用处理以及批处理,这些是多个SQL执行中有共性地方。执行器存在的意义就是去处理这些共性。 如果说每个SQL调用是独立的,不需要缓存,不需要事物也不需集中在一起进行批处理的话,Executor也就没有存在的必要。缓存的具体处理下面会详细分析

个Satement,两天sql语句之间有 其他的sql语句。

6.CachingExecutor

CachingExecutor缓存执行器,用于处理二级缓存的。二级缓存和一级缓存相对独立的逻辑,而且二级缓存可以通过参数控制关闭,而一级缓存是不可以的。综上原因把二级缓存单独抽出来处理。抽取的方式采用了装饰者设计模式,即在CachingExecutor 对原有的执行器进行包装,处理完二级缓存逻辑之后,把SQL执行相关的逻辑交给实至的Executor处理。

[外链图片转存中…(img-HJst6tnF-1630773787493)]

7.执行器总结

执行器的种类有:基础执行器、简单执行器、重用执行器和批处理执行器,此外通过装饰器形式添加了一个缓存执行器。对应功能包括缓存处理、事物处理、重用处理以及批处理,这些是多个SQL执行中有共性地方。执行器存在的意义就是去处理这些共性。 如果说每个SQL调用是独立的,不需要缓存,不需要事物也不需集中在一起进行批处理的话,Executor也就没有存在的必要。缓存的具体处理下面会详细分析


http://chatgpt.dhexx.cn/article/osS7tLBD.shtml

相关文章

ExecutorService

本文翻译自http://tutorials.jenkov.com/java-util-concurrent/executorservice.html&#xff0c;人工翻译&#xff0c;仅供学习交流。 ExecutorService java.util.concurrent.ExecutorService接口是一种能够在后台并发执行任务的异步执行机制。本文中&#xff0c;我将会介绍…

Executor概述

在Java类库中&#xff0c;任务执行的主要抽象不是Thread&#xff0c;而是Executor。 public interface Executor {void execute(Runnable command); }它为灵活且强大的异步任务执行框架提供了基础&#xff0c;该框架能支持多种不同类型的任务执行策略。它提供了一种标准的方法…

Executor框架简介

Executor系统中&#xff0c;将线程任务提交和任务执行进行了解耦的设计; 线程被一对一映射为服务所在操作系统线程&#xff0c;启动时会创建一个操作系统线程&#xff1b;当该线程终止时&#xff0c;这个操作系统线程也会被回收 Executor框架包含的核心接口和主要的实现类 具体…

Executors 源码解析(JDK8)

前言 本文隶属于专栏《100个问题搞定Java并发》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见100个问题搞定Java并发 正文 类注释 /*** Factory and util…

Executor框架

转载请以链接形式标明出处&#xff1a; 本文出自:103style的博客 Java并发编程的艺术笔记 并发编程的挑战Java并发机制的底层实现原理Java内存模型Java并发编程基础Java中的锁的使用和实现介绍Java并发容器和框架Java中的12个原子操作类介绍Java中的并发工具类Java中的线程池E…

Executor执行器

分为四个模块&#xff1a; 1.动态代理MapperProxy 2.SQL会话SqlSesson 3.执行器Executor 4.JDBC处理器StatementHandler 现讲述为SQL会话与执行器 一、SQL会话SqlSesson 该门面模式提供一个统一的门面接口API 该模式提供的一个基本API为增删改查&#xff0c;还会提供提…

Java并发多线程编程——Executors类

目录 一、Executors的理解二、Executors类图结构二、Executors常用的方法三、线程池的创建分为两种方式&#xff08;主要介绍通过Executors类创建的方式&#xff09;1、newFixedThreadPool方法示例2、newSingleThreadExecutor方法示例3、newCachedThreadPool方法4、newSchedule…

Executors一篇就够

Executors框架包含的内容十分的多&#xff1a;看图&#xff1a; 一、各个接口的作用 按照图示关系进行介绍&#xff1a; Executor 该接口作为顶层接口只有一个execute()方法 execute(Runnable r) 该接口接受一个Runnable实例&#xff0c;即要执行的任务ExecutorService 该…

Executors工具类的相关方法

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生。本篇将记录创建线程池的Executors工具类里面的方法&#xff0c;方便加深知识印象和复习使用。 本篇文章记录的基础知识&#xff0c;适合在学Java的小白&#xff0c;也适合复习中&#xff0c;面试中的大佬&a…

java并发编程:Executor、Executors、ExecutorService

Executors 在Java 5之后&#xff0c;并发编程引入了一堆新的启动、调度和管理线程的API。Executor框架便是Java 5中引入的&#xff0c;其内部使用了线程池机制&#xff0c;它在java.util.cocurrent 包下&#xff0c;通过该框架来控制线程的启动、执行和关闭&#xff0c;可以简化…

nlinfit非线性回归拟合

% % 使用指定函数对下述两变量进行曲线拟合 % % yak1*exp(m*t)k2*exp(-m*t); % % 离散点: t[0,4,8,40], % % y[20.09,64.52,85.83,126.75]; % % t-自变量 y-因变量 a,m,k1,k2为常数 % % 用非线性回归nlinfit&#xff0c;如果数据点多些&#xff0c;效果会更好。 脚本&…

matlab的nlinfit函数,用matlab如何进行非线性拟合 nlinfit函数?

用非线性回归nlinfit&#xff0c;如果数据点多些&#xff0c;效果会更好。 function nonlinefit clc;clear; t[0 4 8 40]; y[20.09 64.52 85.83 126.75]; betanlinfit(t,y,myfunc,[1 1 1 1]) abeta(1) k1beta(2) k2beta(3) mbeta(4) tt0:1:40 yyak1*exp(m*tt)k2*exp(-m*tt) plo…

【MATLAB统计分析与应用100例】案例013:matlab读取Excel数据,调用nlinfit函数作一元非线性回归

1. 一元线性回归分析效果预览 2. matlab完整实现代码 %读取数据,绘制散点图** HeadData = xlsread(examp08_02.xls); %从Excel文

matlab中用polyfit、regress、nlinfit等进行详细的回归分析

目录 1.说明2.回归的介绍2-1.前面两篇所发现的一些问题2-1-1.回归和拟合是什么关系?2-1-2.回归到底是做预测还是用来去脏数据?3.三个函数的核心:最小二乘法3-1.介绍3-2.matlab代码4.函数polyfit(线性)5.函数regress(线性)5-1.输出b,bint,r,rint,stats5-2.应用5.2-1.一元…

曲线拟和函数lsqcurvefit nlinfit

转载自&#xff1a;http://panda0411.com/2011/08/29/curve-fit-and-function-lsqcurvefitnlinfit/ 琢磨了好久matlab自带的曲线拟和工具箱, 发现这货只能解决从离散数据得到各种类型的拟和效果, 但是反之貌似没法实现, google一下有这两个函数可以用:lsqcurvefit和nlinfit ls…

Matlab学习手记——非线性数据拟合:nlinfit和lsqcurvefit

目的&#xff1a;通过一个实例了解Matlab的数据拟合函数nlinfit和lsqcurvefit的使用。 结果图 具体数值 p 0.3000 50.0000 0.4000 200.0000 0.3000 800.0000 p1 0.3267 48.3589 0.4030 226.6525 0.2838 809.6680 p2 0.3267 48.3646 0.4031 226.735…

MATLAB多元非线性回归nlinfit拟合圆拟合球拟合函数

先上实验效果&#xff0c;你觉得有帮助可以继续阅读。代码解析在B站有上传视频&#xff08;用户昵称同名&#xff09;&#xff0c;代码也有详细备注。 拟合圆和球面&#xff1a; 拟合多元非线性函数&#xff1a;y p1*x1p2*x1^2p3*x2p4*x2^2exp(-p5*x3)的拟合结果&#xff1a;…

MATLAB 非线性隐函数拟合采坑记录(使用 fsolve solve nlinfit lsqcurvefit函数)

MATLAB 非线性隐函数拟合采坑记录&#xff08;使用 fsolve solve nlinfit lsqcurvefit函数&#xff09; 问题描述解决思路错误示范1代码思路原因解释模型更正更正模型1更正模型2 错误示范2代码思路原因解释模型更正更正模型1更正模型2 总结 问题描述 MATLAB的 nlinfit 和 lsqc…

Matlab多元非线性函数拟合

看了多篇文章&#xff0c;觉得没有一篇比较全&#xff0c;且可以参照的多元非线性函数拟合&#xff0c;看了多篇文章后总结以下内容&#xff0c;主要以示例给出&#xff0c;希望能帮助到大家快速上手。 1.需要用到的函数语法 beta nlinfit(X, Y, modelfun, beta0) X为你的自…

MATLAB中用nlinfit做多元非线性拟合(回归)

MATLAB中有一个多元非线性拟合的功能是nlinfit 基本语法是&#xff1a; beta nlinfit(X,Y,modelfun,beta0) 式子左边的beta可以是一个向量&#xff0c;向量的元素就是要回归的模型中的参数。 式子右边&#xff0c;modelfun是要回归的函数形式。X是函数的自变量数据&#xff1b…