`

tomcat中的BIO应用——JIoEndpoint

阅读更多

一、BIO基础

    BIO即阻塞式I/O,是Java提供的最基本的IO方式,在网络通信中,需要通过Socket在客户端与服务端建立双向链接以实现通信,其主要步骤如下:

    1、服务端监听某个端口是否有链接请求。

    2、客户端向服务端发出链接请求。

    3、服务端向客户端返回Accept接受消息,此时链接成功。

    4、客户端和服务端通过Send(), Write()等方法与对方通信。

    5、关闭链接。

 

    一张BIO的思维导图(图片来源:https://my.oschina.net/langxSpirit/blog/830620



 

     Java分别提供了两个类Socket和ServerSocket,用来表示双向链接的客户端和服务端,基于这两个类,一个简单的网络通信示例如下:

    1、客户端

package com.wang.test.net.io.bio;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * 客户端
 */
public class Client {

    public static void main(String[] args) throws Exception {
        try (
            //向本机的8080端口发送请求
            Socket socket = new Socket("127.0.0.1", 8080);
            //根据标准输入构造BufferedReader对象
            BufferedReader clientInput = new BufferedReader(new InputStreamReader(System.in));
            //通过Socket得到输出流,构造PrintWriter对象
            PrintWriter writer = new PrintWriter(socket.getOutputStream());
            //通过Socket得到输入流,构造BufferedReader对象
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        ){
            //读取输入信息
            String input = clientInput.readLine();
            while ( !input.equals("exit") ){
                //将输入信息发送到服务器
                writer.print(input);
                //刷新输出流,使服务器端可以马上收到请求信息
                writer.flush();
                //读取服务器端返回信息
                System.out.println("服务器端相应为:" + reader.readLine());
                //读取下一条输入信息
                input = clientInput.readLine();
            }
        } catch ( Exception e ) {
            System.out.println(e);
        }
    }
}

     2、服务端

package com.wang.test.net.io.bio;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务器端
 */
public class Server {

    public static void main(String[] args) {
        try(
            //创建ServerSocket监听端口8080
            ServerSocket server = new ServerSocket(8080);
            //等待客户端请求
            Socket socket = server.accept();
            //根据标准输入构造BufferedReader对象
            BufferedReader serverInput = new BufferedReader(new InputStreamReader(System.in));
            //通过Socket对象得到输出流,BufferedReader
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //通过Socket对象得到输出流,并构造PrintWrite对象
            PrintWriter writer = new PrintWriter(socket.getOutputStream());
        ){
            //读取客户端请求
            System.out.println("客户端请求:" + reader.readLine());
            //输入服务端相应
            String input = serverInput.readLine();
            //如果输入内容为"exit",则退出
            while (!input.equals("exit")){
                writer.print(input);
                //向客户端输出该字符串
                writer.flush();
                //读取客户端请求
                System.out.println("客户端请求:" + reader.readLine());
                //输入服务器相应
                input = serverInput.readLine();
            }
        } catch ( Exception e ){
            System.out.println(e);
        }
    }
}

 

二、JIoEndpoint

    Tomcat服务器实现中,Tomcat的IO监听由Endpoint完成,具体到BIO是JIoEndpoint,JIoEndpoint启动过程如下:

    1、根据IP地址(多IP的情况)及端口创建ServerSocket实例;JIoEndpoint类bind()方法部分代码

        if (serverSocket == null) {	//根据IP地址(多IP的情况)及端口创建ServerSocket实例
            try {
                if (getAddress() == null) {
                    serverSocket = serverSocketFactory.createSocket(getPort(),
                            getBacklog());
                } else {
                    serverSocket = serverSocketFactory.createSocket(getPort(),
                            getBacklog(), getAddress());
                }
            } catch (BindException orig) {
                String msg;
                if (getAddress() == null)
                    msg = orig.getMessage() + " <null>:" + getPort();
                else
                    msg = orig.getMessage() + " " +
                            getAddress().toString() + ":" + getPort();
                BindException be = new BindException(msg);
                be.initCause(orig);
                throw be;
            }
        }

     2、如果Connector没有配置共享线程池,创建请求处理线程池;JIoEndpoint类startInternal()方法部分代码

            // Create worker collection
            if (getExecutor() == null) {	//如果Connector没有配置共享线程池
                createExecutor();	//创建请求处理线程池
            }

     createExecutor()方法实现在JIoEndpoint父抽象类中

    public void createExecutor() {
        internalExecutor = true;
        TaskQueue taskqueue = new TaskQueue();
        TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
        executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
        taskqueue.setParent( (ThreadPoolExecutor) executor);
    }

     3、根据AcceptThreadCount配置的数量,创建并启动Accept线程,JIoEndpoint类startInternal()方法部分代码

startAcceptorThreads();	//根据AcceptorThreadCount配置的数量,创建并启动Acceptor线程

     startAcceptThread方法实现在父抽象类中:

/**
     * 根据AcceptorThreadCount配置的数量,创建并启动Acceptor线程
     */
    protected final void startAcceptorThreads() {
        int count = getAcceptorThreadCount();
        acceptors = new Acceptor[count];

        for (int i = 0; i < count; i++) {
            acceptors[i] = createAcceptor();
            String threadName = getName() + "-Acceptor-" + i;
            acceptors[i].setThreadName(threadName);
            Thread t = new Thread(acceptors[i], threadName);	//线程单独启动,并未放到线程池中,因此不会影响请求并发处理
            t.setPriority(getAcceptorThreadPriority());
            t.setDaemon(getDaemon());
            t.start();
        }
    }

     在该方法中,这些线程都是单独启动的,因此不会影响请求并发数量。createAcceptor获取JIoEndpoint类中的内部类Accept,该内部类继承JIoEndpoint父抽象类中的内部类Accept, Acceptor实现了Runnable接口,负责轮询接收客户端请求。JIoEndpoint类中的内部类Acceptor

/**
     * 负责轮询接收客户端请求, 还会检测EndPoint状态以及最大连接数
     * The background thread that listens for incoming TCP/IP connections and
     * hands them off to an appropriate processor.
     */
    protected class Acceptor extends AbstractEndpoint.Acceptor {

        @Override
        public void run() {

            int errorDelay = 0;

            // Loop until we receive a shutdown command
            while (running) {

                // Loop if endpoint is paused
                while (paused && running) {
                    state = AcceptorState.PAUSED;
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }

                if (!running) {
                    break;
                }
                state = AcceptorState.RUNNING;

                try {
                    //if we have reached max connections, wait
                    countUpOrAwaitConnection();

                    Socket socket = null;
                    try {
                        // Accept the next incoming connection from the server
                        // socket
                        socket = serverSocketFactory.acceptSocket(serverSocket);	
                    } catch (IOException ioe) {
                        countDownConnection();
                        // Introduce delay if necessary
                        errorDelay = handleExceptionWithDelay(errorDelay);
                        // re-throw
                        throw ioe;
                    }
                    // Successful accept, reset the error delay
                    errorDelay = 0;

                    // Configure the socket
                    if (running && !paused && setSocketOptions(socket)) {	//当接收到客户端请求
                        // Hand this socket off to an appropriate processor
                        if (!processSocket(socket)) {	//
                            countDownConnection();
                            // Close socket right away
                            closeSocket(socket);
                        }
                    } else {
                        countDownConnection();
                        // Close socket right away
                        closeSocket(socket);
                    }
                } catch (IOException x) {
                    if (running) {
                        log.error(sm.getString("endpoint.accept.fail"), x);
                    }
                } catch (NullPointerException npe) {
                    if (running) {
                        log.error(sm.getString("endpoint.accept.fail"), npe);
                    }
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    log.error(sm.getString("endpoint.accept.fail"), t);
                }
            }
            state = AcceptorState.ENDED;
        }
    }

    4、当接收到客户端请求后,创建SocketProcessor对象,并提交给线程池处理。

    5、SocketProcessor并未直接处理Socket,而是将其交由具体的协议处理类,BIO方式下的HTTP协议使用HTTP11Processor。

    JIoEndpoint类中的内部类SocketProcessor

/**
     * This class is the equivalent of the Worker, but will simply use in an
     * external Executor thread pool.
     * SocketProcessor并未直接处理Socket,而是将其交由具体的协议处理类,如Http11Processor用于处理BIO方式下的HTTP协议
     */
    protected class SocketProcessor implements Runnable {

        protected SocketWrapper<Socket> socket = null;
        protected SocketStatus status = null;

        public SocketProcessor(SocketWrapper<Socket> socket) {
            if (socket==null) throw new NullPointerException();
            this.socket = socket;
        }

        public SocketProcessor(SocketWrapper<Socket> socket, SocketStatus status) {
            this(socket);
            this.status = status;
        }

        @Override
        public void run() {
            boolean launch = false;
            synchronized (socket) {
                try {
                    SocketState state = SocketState.OPEN;
                    handler.beforeHandshake(socket);
                    try {
                        // SSL handshake
                        serverSocketFactory.handshake(socket.getSocket());
                    } catch (Throwable t) {
                        ExceptionUtils.handleThrowable(t);
                        if (log.isDebugEnabled()) {
                            log.debug(sm.getString("endpoint.err.handshake"), t);
                        }
                        // Tell to close the socket
                        state = SocketState.CLOSED;
                    }

                    if ((state != SocketState.CLOSED)) {
                        if (status == null) {
                            state = handler.process(socket, SocketStatus.OPEN_READ);
                        } else {
                            state = handler.process(socket,status);
                        }
                    }
                    if (state == SocketState.CLOSED) {
                        // Close socket
                        if (log.isTraceEnabled()) {
                            log.trace("Closing socket:"+socket);
                        }
                        countDownConnection();
                        try {
                            socket.getSocket().close();
                        } catch (IOException e) {
                            // Ignore
                        }
                    } else if (state == SocketState.OPEN ||
                            state == SocketState.UPGRADING  ||
                            state == SocketState.UPGRADED){
                        socket.setKeptAlive(true);
                        socket.access();
                        launch = true;
                    } else if (state == SocketState.LONG) {
                        socket.access();
                        waitingRequests.add(socket);
                    }
                } finally {
                    if (launch) {
                        try {
                            getExecutor().execute(new SocketProcessor(socket, SocketStatus.OPEN_READ));
                        } catch (RejectedExecutionException x) {
                            log.warn("Socket reprocessing request was rejected for:"+socket,x);
                            try {
                                //unable to handle connection at this time
                                handler.process(socket, SocketStatus.DISCONNECT);
                            } finally {
                                countDownConnection();
                            }


                        } catch (NullPointerException npe) {
                            if (running) {
                                log.error(sm.getString("endpoint.launch.fail"),
                                        npe);
                            }
                        }
                    }
                }
            }
            socket = null;
            // Finish up this request
        }

    }

 6、此外,JIoEndpoint还构造了一个单独的线程用于检测超时请求。JIoEndpoint类中的startInternal方法的部分代码

      // Start async timeout thread 用于检测超时请求
      setAsyncTimeout(new AsyncTimeout());
      Thread timeoutThread = new Thread(getAsyncTimeout(), getName() + "-AsyncTimeout");
      timeoutThread.setPriority(threadPriority);
      timeoutThread.setDaemon(true);
      timeoutThread.start();

 

 

 

  • 大小: 119.7 KB
1
0
分享到:
评论

相关推荐

    从连接器组件看Tomcat的线程模型——BIO模式(推荐)

    在Tomcat中,BIO模式下,`JIoEndpoint`组件扮演了核心角色,它启动监听特定端口的ServerSocket,一旦有新的连接请求,这个请求会被放入线程池进行处理。线程池中的线程会调用`Http11Processor`这个协议解析器,对...

    ccnp-300-430.pdf

    内容概要:本文档《ccnp_300-430.pdf》涵盖了与Cisco无线网络配置相关的多个选择题及其答案解析。文档详细探讨了FlexConnect AP在不同模式下的行为、AP模式和子模式的选择、客户端特征配置、图像传输优化、Cisco OEAP配置、QoS设置、多播配置、安全措施(如入侵保护、恶意AP检测)、位置服务配置以及BYOD策略实施等内容。文档不仅提供了具体的配置命令和选项,还解释了每种配置背后的逻辑和技术原理。 适合人群:具备一定网络基础知识,特别是对Cisco无线网络设备有一定了解的技术人员,包括但不限于网络管理员、无线网络工程师和CCNP认证考生。 使用场景及目标: ① 为无线网络工程师提供实际操作指导,确保在不同场景下正确配置Cisco无线设备; ② 帮助CCNP认证考生复习并掌握相关知识点; ③ 协助IT管理员解决日常无线网络管理中的常见问题,如连接不稳定、性能不佳或安全性问题; ④ 支持企业IT部门制定和实施BYOD策略,确保员工个人设备接入公司网络的安全性和效率。 阅读建议:由于文档内容较为专业且技术性强,建议读者首先熟悉Cisco无线网络的基本概念和术语。在阅读过程中,应结合具体的工作环境和需求进行理解,并尝试将所学知识应用到实际工作中。对于不熟悉的术语或配置命令,可以通过查阅官方文档或在线资源进一步学习。此外,通过模拟环境练习配置也是巩固知识的有效方法。

    电力系统调频中风火联合控制及特性分析:基于IEEE9节点系统的仿真研究

    内容概要:本文探讨了电力系统频率稳定性问题,特别是在风电大规模接入背景下,传统火电和水电调频方法面临的挑战及其解决方案。文中通过构建IEEE9节点系统模型,利用Simulink和Python进行仿真,比较了单一火电调频与风火联合调频的效果。研究表明,引入虚拟惯性控制和下垂控制可以显著提高系统的响应速度和稳定性,同时指出水电调频中存在的水锤效应对频率稳定的影响及相应的抑制措施。 适合人群:从事电力系统研究的专业人士、高校相关专业师生以及对电力系统调频感兴趣的工程技术人员。 使用场景及目标:适用于希望深入了解电力系统调频机制的研究人员和技术人员,旨在帮助他们掌握最新的调频技术和理论,提升实际工作中解决问题的能力。 其他说明:文章不仅提供了详细的数学模型和仿真代码,还分享了一些实用的小技巧,如参数优化方法和仿真加速策略,有助于读者更好地理解和应用所介绍的技术。

    COMSOL中热湿耦合仿真的蒸汽冷凝建模与优化

    内容概要:本文详细介绍了如何在COMSOL中进行热湿耦合仿真,特别是针对蒸汽在顶部冷凝的复杂场景。首先搭建了一个20cm高的多孔介质层模型,设置了必要的物理场(如热湿传递和层流),并讨论了材料参数的选择,特别是蒸汽扩散系数和孔隙度的变化。接着深入探讨了边界条件的设置方法,包括蒸汽入口的速度和温度控制,以及冷凝边界的处理方式。文中还强调了求解器设置的重要性,提出了稳态解和瞬态解相结合的方法,并给出了具体的网格划分技巧。最后,文章提供了关于冷凝水量计算和表面张力处理的实用建议,确保仿真结果更加接近实际情况。 适合人群:具有一定COMSOL使用经验的研究人员和技术人员,特别是从事热湿耦合仿真领域的专业人士。 使用场景及目标:适用于需要精确模拟蒸汽冷凝过程的实际工程项目,如工业设备设计、建筑环境控制等。目标是帮助用户掌握COMSOL中热湿耦合仿真的关键技术,提高仿真精度和可靠性。 其他说明:文中提供的代码片段和具体参数设置对于初学者来说非常有价值,能够快速上手并应用于实际工作中。此外,文章还分享了一些常见的错误及其解决方法,有助于避免仿真过程中常见的陷阱。

    flink-table-api-java-1.13.4.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    基于西门子S7-200smart PLC的恒压供水系统设计与实现

    内容概要:本文详细介绍了基于西门子S7-200smart PLC和西门子触摸屏构建的恒压供水(无负压供水)系统。系统通过PLC对电机进行智能控制,确保水压稳定。主要功能包括一拖二自动控制、PID调节实现恒压控制以及友好的人机交互界面。文中还展示了详细的PLC控制代码和PID控制算法,并讨论了电气图纸的设计要点和实际工程中的注意事项。 适合人群:从事自动化控制领域的工程师和技术人员,尤其是熟悉PLC编程和恒压供水系统设计的专业人士。 使用场景及目标:适用于需要稳定供水的工业生产和居民生活场景,旨在提高供水系统的可靠性和稳定性,减少设备磨损和能源浪费。 其他说明:文章不仅提供了完整的系统设计方案,还包括了许多实际调试经验和常见问题的解决方法,有助于读者更好地理解和实施该系统。

    flink-connector-jdbc_2.12-1.14.1.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    嵌入式系统中滑模观测器与PLL的C代码实现及其在STM32F1平台的应用

    内容概要:本文详细介绍了滑模观测器和PLL在STM32F1平台上的C代码实现。滑模观测器用于估计系统内部状态,尤其适用于电机控制领域;PLL则用于确保输出信号相位与输入信号相位保持一致。文中展示了两种滑模观测器的实现方法:一种采用符号函数进行硬切换,另一种采用饱和函数进行软化处理。此外,文章还强调了使用TI的IQmath库进行定点计算加速,以提高运算效率并减少资源占用。通过具体的代码示例和调试技巧,作者分享了如何在STM32F1平台上实现高效稳定的滑模观测器和PLL系统。 适合人群:嵌入式系统开发者、电机控制系统工程师、熟悉C语言编程的技术人员。 使用场景及目标:① 实现高效的滑模观测器和PLL系统,应用于电机控制和其他实时性要求较高的场景;② 学习如何使用IQmath库进行定点计算加速,优化嵌入式系统的性能;③ 掌握调试技巧,确保系统稳定运行。 其他说明:文章提供了详细的代码示例和调试经验,帮助读者更好地理解和实现滑模观测器和PLL系统。同时,文中提到的一些注意事项和常见问题解决方案也非常实用。

    flink-table-common-1.7.2.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    groovy-2.6.0-alpha-2.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    电力电子领域逆变器重复控制系统的C语言实现与Simulink仿真优化

    内容概要:本文详细介绍了如何利用C语言在Simulink环境中构建逆变器的重复控制系统,旨在将逆变器的总谐波畸变率(THD)降低至0.47%。文中首先展示了核心的C语言结构体和函数,如RepetitiveController结构体用于封装延迟存储器、零相位滤波器和低通滤波器,repetitive_control函数则实现了核心算法。接着,文章解释了离散化处理的方法,包括主电路和控制部分的不同步长运行机制,以及多速率仿真的应用。此外,还讨论了陷波器的具体实现及其参数调整,强调了双线性变换在滤波器设计中的重要性。最后,文章提到了代码的高效移植性,指出通过这种方式可以在仿真阶段就为后续的实际硬件部署做好准备,大大减少了调试时间和复杂度。 适合人群:从事电力电子领域的工程师和技术人员,尤其是对逆变器控制和信号处理有一定了解的人群。 使用场景及目标:适用于需要精确控制逆变器输出质量的应用场合,如光伏逆变器、UPS电源等。主要目标是通过高效的算法设计和优化,确保逆变器输出的THD达到极低水平,同时提高代码的可移植性和易维护性。 其他说明:本文不仅提供了详细的理论背景和技术细节,还分享了许多实践经验,如环形缓冲区的使用、陷波器的参数选择等,对于理解和实施逆变器控制具有很高的参考价值。

    Outlook新邮件到达时不显示通知

    Outlook新邮件到达时不显示通知

    三相维也纳PFC开关电源及移相全桥、LLC量产方案详解与调试经验

    内容概要:本文详细介绍了三相维也纳PFC开关电源的设计、调试经验和量产方案。主要内容涵盖三相AC输入、无桥PFC结构、±400V DC输出的特点及其优势。文中提供了关键代码片段,如PFC开关频率控制、PWM初始化、过流保护等,并深入探讨了原理图设计、PCB布局要点以及EMI滤波措施。此外,还涉及移相全桥和LLC方案的应用,特别是在高效率、高功率密度场合的表现。作者分享了大量实战经验,包括硬件选型、软件调试技巧和常见问题解决方法。 适合人群:从事电力电子、工业电源设计的技术人员,尤其是对三相PFC、移相全桥和LLC技术感兴趣的工程师。 使用场景及目标:帮助读者理解和掌握三相维也纳PFC的工作原理和技术细节,提供实用的调试经验和量产解决方案,适用于新能源充电桩、大功率服务器电源等领域的产品开发。 其他说明:文章不仅涵盖了理论知识,还包括大量的实战案例和代码示例,有助于读者在实践中快速上手并解决问题。

    黑板卡通熊儿童教学教案课件模板.pptx

    黑板卡通熊儿童教学教案课件模板

    基于Python的沟槽开挖土方量计算:断面法的应用与优化

    内容概要:本文详细介绍了如何利用Python编程语言进行沟槽开挖土方量的计算,采用断面法作为主要手段。首先定义了基本参数如原地面标高、设计沟底标高等,接着通过函数calculate_section_area实现了断面面积的计算,考虑了边坡系数的影响。然后,通过遍历多个断面并应用平均面积法或棱台公式求解总土方量。此外,还探讨了如何使用matplotlib库绘制断面图以及处理复杂地形的方法,如使用pandas处理Excel数据和geopandas进行空间分析。文中强调了实际工程项目中需要注意的问题,如断面间距的选择、不同地质层的分段计算等。 适合人群:从事土木工程、市政建设等领域的一线工程师和技术人员,尤其是那些希望提高工作效率、减少手工计算错误的人群。 使用场景及目标:适用于需要精确计算沟槽开挖土方量的实际工程项目中,帮助工程师们更好地规划施工进度、控制成本。同时,也为后续的设计调整提供了科学依据。 其他说明:本文不仅提供了具体的Python代码实现,还分享了许多实践经验,如避免常见的计算陷阱、确保数据精度等。对于想要深入理解土方量计算原理及其自动化实现的人来说,是一份非常有价值的参考资料。

    groovy-3.0.0.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    MLP多层感知机在Matlab中的时间序列预测实现及性能评估

    内容概要:本文详细介绍了如何利用Matlab实现MLP(多层感知机)进行时间序列预测。首先,通过对一维时间序列数据进行预处理,包括加载、划分训练集和测试集以及标准化。接着,构建了一个带有单隐藏层的MLP模型,并设置了训练参数,如隐藏层神经元个数、学习率和最大迭代次数。随后,使用训练好的模型对测试数据进行了预测,并通过R²和MAE两个指标评估了模型的性能。最后,提供了完整的代码实现和一些优化建议,如调整验证集比例和加入置信区间可视化。 适合人群:具有一定编程基础,尤其是熟悉Matlab和机器学习基础知识的研究人员和技术爱好者。 使用场景及目标:适用于需要进行时间序列预测的场景,如金融市场的趋势分析、气象预报等。目标是帮助读者掌握MLP在时间序列预测中的具体实现方法,理解各个步骤的作用,并能够根据自己的数据集进行相应的调整和优化。 其他说明:文中还提到了一些实用的小技巧,例如如何避免常见错误(如数据格式问题)、选择合适的隐藏层神经元数量以及如何正确地进行数据标准化等。此外,强调了在实际应用中可以通过调整模型参数来提高预测精度。

    修改PDF元属性作者信息

    修改PDF元属性作者信息

    42页-中小学新建校智慧校园顶层设计规划方案.pdf

    踏入智慧校园的新时代,一场科技与教育的深度融合正在悄然上演。本方案以大数据、云计算、AI等前沿技术为基石,为校园管理带来前所未有的变革与便捷。 一、一键智控,校园管理轻松升级 想象一下,只需轻点手机,就能实现校园的全面智控。从教学教务到行政后勤,从师生考勤到校园安全,智慧校园解决方案一网打尽。通过构建统一的数据中台,实现各系统间的无缝对接与数据共享,让繁琐的管理工作变得轻松高效。智能排课、自动考勤、在线审批……一系列智能应用让校园管理如虎添翼,让校长和老师们从繁琐的事务中解放出来,专注于教学创新与质量提升。 二、寓教于乐,学习生活趣味无穷 智慧校园不仅让管理变得更简单,更让学习生活变得趣味无穷。AI赋能的教学系统能根据学生的学习习惯和能力,提供个性化的学习路径与资源推荐,让学习变得更加高效有趣。同时,丰富的课外活动与社团管理模块,让孩子们的课余生活也充满了欢声笑语。从智慧班牌到智能录播,从家校共育到虚拟实验室,智慧校园让每一个角落都充满了探索的乐趣与知识的光芒。 三、安全守护,校园生活无忧无虑 在智慧校园的守护下,校园生活变得更加安全无忧。通过高清视频监控、智能预警系统与人脸识别技术,校园安全得到了全方位保障。无论是外来人员的入侵还是学生的异常行为,都能被及时发现并处理。同时,智能化的健康管理系统还能实时监测师生的健康状况,为校园防疫工作提供有力支持。智慧校园,用科技的力量为每一位师生筑起了一道坚实的安全防线,让校园生活更加安心、舒心。

    锂电池建模仿真:基于二阶RC等效电路模型的Python实现及其应用

    内容概要:本文详细介绍了锂电池二阶RC等效电路模型的构建与仿真方法。首先解释了选择二阶RC模型的原因,即它能够平衡复杂性和准确性,有效描述锂电池在充放电过程中的动态特性。接着展示了该模型的具体结构,包括开路电压源、欧姆内阻及两个RC支路。然后通过Python代码演示了如何实现模型的仿真,利用numpy和matplotlib库完成参数设置、模型仿真和结果可视化。此外,还讨论了参数辨识的方法,如最小二乘拟合,并强调了模型验证的重要性。最后指出该模型可用于电池管理系统(BMS)中,帮助实时监测和预测电池状态。 适合人群:从事锂电池研究、电池管理系统开发的技术人员,以及对电池建模感兴趣的科研工作者。 使用场景及目标:适用于需要理解和预测锂电池动态特性的场合,如电动车、储能系统等领域。目标是提高对锂电池行为的理解,优化电池管理系统的性能。 其他说明:文中提供了详细的代码示例,便于读者动手实践。同时提醒读者注意模型参数随温度变化的情况,建议在不同温度条件下进行参数标定。

Global site tag (gtag.js) - Google Analytics