聊聊HttpClientBuilder
序
本文主要研究一下HttpClientBuilder
HttpClientBuilder
httpclient-4.5.10-sources.jar!/org/apache/http/impl/client/HttpClientBuilder.java
public class HttpClientBuilder {public static HttpClientBuilder create() {return new HttpClientBuilder();}protected HttpClientBuilder() {super();}public CloseableHttpClient build() {// Create main request executor// We copy the instance fields to avoid changing them, and rename to avoid accidental use of the wrong versionPublicSuffixMatcher publicSuffixMatcherCopy = this.publicSuffixMatcher;if (publicSuffixMatcherCopy == null) {publicSuffixMatcherCopy = PublicSuffixMatcherLoader.getDefault();}HttpRequestExecutor requestExecCopy = this.requestExec;if (requestExecCopy == null) {requestExecCopy = new HttpRequestExecutor();}HttpClientConnectionManager connManagerCopy = this.connManager;if (connManagerCopy == null) {LayeredConnectionSocketFactory sslSocketFactoryCopy = this.sslSocketFactory;if (sslSocketFactoryCopy == null) {final String[] supportedProtocols = systemProperties ? split(System.getProperty("https.protocols")) : null;final String[] supportedCipherSuites = systemProperties ? split(System.getProperty("https.cipherSuites")) : null;HostnameVerifier hostnameVerifierCopy = this.hostnameVerifier;if (hostnameVerifierCopy == null) {hostnameVerifierCopy = new DefaultHostnameVerifier(publicSuffixMatcherCopy);}if (sslContext != null) {sslSocketFactoryCopy = new SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifierCopy);} else {if (systemProperties) {sslSocketFactoryCopy = new SSLConnectionSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault(),supportedProtocols, supportedCipherSuites, hostnameVerifierCopy);} else {sslSocketFactoryCopy = new SSLConnectionSocketFactory(SSLContexts.createDefault(),hostnameVerifierCopy);}}}@SuppressWarnings("resource")final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactoryCopy).build(),null,null,dnsResolver,connTimeToLive,connTimeToLiveTimeUnit != null ? connTimeToLiveTimeUnit : TimeUnit.MILLISECONDS);if (defaultSocketConfig != null) {poolingmgr.setDefaultSocketConfig(defaultSocketConfig);}if (defaultConnectionConfig != null) {poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig);}if (systemProperties) {String s = System.getProperty("http.keepAlive", "true");if ("true".equalsIgnoreCase(s)) {s = System.getProperty("http.maxConnections", "5");final int max = Integer.parseInt(s);poolingmgr.setDefaultMaxPerRoute(max);poolingmgr.setMaxTotal(2 * max);}}if (maxConnTotal > 0) {poolingmgr.setMaxTotal(maxConnTotal);}if (maxConnPerRoute > 0) {poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);}connManagerCopy = poolingmgr;}ConnectionReuseStrategy reuseStrategyCopy = this.reuseStrategy;if (reuseStrategyCopy == null) {if (systemProperties) {final String s = System.getProperty("http.keepAlive", "true");if ("true".equalsIgnoreCase(s)) {reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE;} else {reuseStrategyCopy = NoConnectionReuseStrategy.INSTANCE;}} else {reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE;}}ConnectionKeepAliveStrategy keepAliveStrategyCopy = this.keepAliveStrategy;if (keepAliveStrategyCopy == null) {keepAliveStrategyCopy = DefaultConnectionKeepAliveStrategy.INSTANCE;}AuthenticationStrategy targetAuthStrategyCopy = this.targetAuthStrategy;if (targetAuthStrategyCopy == null) {targetAuthStrategyCopy = TargetAuthenticationStrategy.INSTANCE;}AuthenticationStrategy proxyAuthStrategyCopy = this.proxyAuthStrategy;if (proxyAuthStrategyCopy == null) {proxyAuthStrategyCopy = ProxyAuthenticationStrategy.INSTANCE;}UserTokenHandler userTokenHandlerCopy = this.userTokenHandler;if (userTokenHandlerCopy == null) {if (!connectionStateDisabled) {userTokenHandlerCopy = DefaultUserTokenHandler.INSTANCE;} else {userTokenHandlerCopy = NoopUserTokenHandler.INSTANCE;}}String userAgentCopy = this.userAgent;if (userAgentCopy == null) {if (systemProperties) {userAgentCopy = System.getProperty("http.agent");}if (userAgentCopy == null && !defaultUserAgentDisabled) {userAgentCopy = VersionInfo.getUserAgent("Apache-HttpClient","org.apache.http.client", getClass());}}ClientExecChain execChain = createMainExec(requestExecCopy,connManagerCopy,reuseStrategyCopy,keepAliveStrategyCopy,new ImmutableHttpProcessor(new RequestTargetHost(), new RequestUserAgent(userAgentCopy)),targetAuthStrategyCopy,proxyAuthStrategyCopy,userTokenHandlerCopy);execChain = decorateMainExec(execChain);HttpProcessor httpprocessorCopy = this.httpprocessor;if (httpprocessorCopy == null) {final HttpProcessorBuilder b = HttpProcessorBuilder.create();if (requestFirst != null) {for (final HttpRequestInterceptor i: requestFirst) {b.addFirst(i);}}if (responseFirst != null) {for (final HttpResponseInterceptor i: responseFirst) {b.addFirst(i);}}b.addAll(new RequestDefaultHeaders(defaultHeaders),new RequestContent(),new RequestTargetHost(),new RequestClientConnControl(),new RequestUserAgent(userAgentCopy),new RequestExpectContinue());if (!cookieManagementDisabled) {b.add(new RequestAddCookies());}if (!contentCompressionDisabled) {if (contentDecoderMap != null) {final List<String> encodings = new ArrayList<String>(contentDecoderMap.keySet());Collections.sort(encodings);b.add(new RequestAcceptEncoding(encodings));} else {b.add(new RequestAcceptEncoding());}}if (!authCachingDisabled) {b.add(new RequestAuthCache());}if (!cookieManagementDisabled) {b.add(new ResponseProcessCookies());}if (!contentCompressionDisabled) {if (contentDecoderMap != null) {final RegistryBuilder<InputStreamFactory> b2 = RegistryBuilder.create();for (final Map.Entry<String, InputStreamFactory> entry: contentDecoderMap.entrySet()) {b2.register(entry.getKey(), entry.getValue());}b.add(new ResponseContentEncoding(b2.build()));} else {b.add(new ResponseContentEncoding());}}if (requestLast != null) {for (final HttpRequestInterceptor i: requestLast) {b.addLast(i);}}if (responseLast != null) {for (final HttpResponseInterceptor i: responseLast) {b.addLast(i);}}httpprocessorCopy = b.build();}execChain = new ProtocolExec(execChain, httpprocessorCopy);execChain = decorateProtocolExec(execChain);// Add request retry executor, if not disabledif (!automaticRetriesDisabled) {HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;if (retryHandlerCopy == null) {retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE;}execChain = new RetryExec(execChain, retryHandlerCopy);}HttpRoutePlanner routePlannerCopy = this.routePlanner;if (routePlannerCopy == null) {SchemePortResolver schemePortResolverCopy = this.schemePortResolver;if (schemePortResolverCopy == null) {schemePortResolverCopy = DefaultSchemePortResolver.INSTANCE;}if (proxy != null) {routePlannerCopy = new DefaultProxyRoutePlanner(proxy, schemePortResolverCopy);} else if (systemProperties) {routePlannerCopy = new SystemDefaultRoutePlanner(schemePortResolverCopy, ProxySelector.getDefault());} else {routePlannerCopy = new DefaultRoutePlanner(schemePortResolverCopy);}}// Optionally, add service unavailable retry executorfinal ServiceUnavailableRetryStrategy serviceUnavailStrategyCopy = this.serviceUnavailStrategy;if (serviceUnavailStrategyCopy != null) {execChain = new ServiceUnavailableRetryExec(execChain, serviceUnavailStrategyCopy);}// Add redirect executor, if not disabledif (!redirectHandlingDisabled) {RedirectStrategy redirectStrategyCopy = this.redirectStrategy;if (redirectStrategyCopy == null) {redirectStrategyCopy = DefaultRedirectStrategy.INSTANCE;}execChain = new RedirectExec(execChain, routePlannerCopy, redirectStrategyCopy);}// Optionally, add connection back-off executorif (this.backoffManager != null && this.connectionBackoffStrategy != null) {execChain = new BackoffStrategyExec(execChain, this.connectionBackoffStrategy, this.backoffManager);}Lookup<AuthSchemeProvider> authSchemeRegistryCopy = this.authSchemeRegistry;if (authSchemeRegistryCopy == null) {authSchemeRegistryCopy = RegistryBuilder.<AuthSchemeProvider>create().register(AuthSchemes.BASIC, new BasicSchemeFactory()).register(AuthSchemes.DIGEST, new DigestSchemeFactory()).register(AuthSchemes.NTLM, new NTLMSchemeFactory()).register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory()).register(AuthSchemes.KERBEROS, new KerberosSchemeFactory()).build();}Lookup<CookieSpecProvider> cookieSpecRegistryCopy = this.cookieSpecRegistry;if (cookieSpecRegistryCopy == null) {cookieSpecRegistryCopy = CookieSpecRegistries.createDefault(publicSuffixMatcherCopy);}CookieStore defaultCookieStore = this.cookieStore;if (defaultCookieStore == null) {defaultCookieStore = new BasicCookieStore();}CredentialsProvider defaultCredentialsProvider = this.credentialsProvider;if (defaultCredentialsProvider == null) {if (systemProperties) {defaultCredentialsProvider = new SystemDefaultCredentialsProvider();} else {defaultCredentialsProvider = new BasicCredentialsProvider();}}List<Closeable> closeablesCopy = closeables != null ? new ArrayList<Closeable>(closeables) : null;if (!this.connManagerShared) {if (closeablesCopy == null) {closeablesCopy = new ArrayList<Closeable>(1);}final HttpClientConnectionManager cm = connManagerCopy;if (evictExpiredConnections || evictIdleConnections) {final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(cm,maxIdleTime > 0 ? maxIdleTime : 10, maxIdleTimeUnit != null ? maxIdleTimeUnit : TimeUnit.SECONDS,maxIdleTime, maxIdleTimeUnit);closeablesCopy.add(new Closeable() {@Overridepublic void close() throws IOException {connectionEvictor.shutdown();try {connectionEvictor.awaitTermination(1L, TimeUnit.SECONDS);} catch (final InterruptedException interrupted) {Thread.currentThread().interrupt();}}});connectionEvictor.start();}closeablesCopy.add(new Closeable() {@Overridepublic void close() throws IOException {cm.shutdown();}});}return new InternalHttpClient(execChain,connManagerCopy,routePlannerCopy,cookieSpecRegistryCopy,authSchemeRegistryCopy,defaultCookieStore,defaultCredentialsProvider,defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT,closeablesCopy);}
}
HttpClientBuilder提供了静态方法create用于创建builder,其build方法用于创建CloseableHttpClient,它主要是构建ClientExecChain(
HttpRequestExecutor、HttpClientConnectionManager、ConnectionReuseStrategy、ConnectionKeepAliveStrategy、AuthenticationStrategy、UserTokenHandler
)、ProtocolExec(ClientExecChain、HttpProcessor
)、RetryExec(ClientExecChain、HttpRequestRetryHandler
)、RedirectExec(HttpRoutePlanner、ServiceUnavailableRetryStrategy、RedirectStrategy
)、BackoffStrategyExec;最后构建的是InternalHttpClient
SSLContext
org/apache/http/ssl/SSLContexts.java
对于sslContext不为null的则创建SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifierCopy),为null的话,则通过SSLContexts.createDefault()来创建默认的SSLContext
public static SSLContext createDefault() throws SSLInitializationException {try {final SSLContext sslContext = SSLContext.getInstance(SSLContextBuilder.TLS);sslContext.init(null, null, null);return sslContext;} catch (final NoSuchAlgorithmException ex) {throw new SSLInitializationException(ex.getMessage(), ex);} catch (final KeyManagementException ex) {throw new SSLInitializationException(ex.getMessage(), ex);}}
HostnameVerifier
若hostnameVerifier为null,则创建默认的DefaultHostnameVerifier
public DefaultHostnameVerifier(final PublicSuffixMatcher publicSuffixMatcher) {this.publicSuffixMatcher = publicSuffixMatcher;}public DefaultHostnameVerifier() {this(null);}@Overridepublic boolean verify(final String host, final SSLSession session) {try {final Certificate[] certs = session.getPeerCertificates();final X509Certificate x509 = (X509Certificate) certs[0];verify(host, x509);return true;} catch (final SSLException ex) {if (log.isDebugEnabled()) {log.debug(ex.getMessage(), ex);}return false;}}
PoolingHttpClientConnectionManager
org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL)
public class PoolingHttpClientConnectionManagerimplements HttpClientConnectionManager, ConnPoolControl<HttpRoute>, Closeable {private final ConfigData configData;private final CPool pool;private final HttpClientConnectionOperator connectionOperator;private final AtomicBoolean isShutDown;public PoolingHttpClientConnectionManager(final HttpClientConnectionOperator httpClientConnectionOperator,final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,final long timeToLive, final TimeUnit timeUnit) {super();this.configData = new ConfigData();this.pool = new CPool(new InternalConnectionFactory(this.configData, connFactory), 2, 20, timeToLive, timeUnit);this.pool.setValidateAfterInactivity(2000);this.connectionOperator = Args.notNull(httpClientConnectionOperator, "HttpClientConnectionOperator");this.isShutDown = new AtomicBoolean(false);}@Overrideprotected void finalize() throws Throwable {try {shutdown();} finally {super.finalize();}}@Overridepublic void close() {shutdown();}//......
}
PoolingHttpClientConnectionManager实现了HttpClientConnectionManager、ConnPoolControl、Closeable接口,它使用了CPool作为连接池来管理连接,默认的maxPerRoute为2,maxTotal为20
小结
apache的httpclient的HttpClientBuilder提供了构建CloseableHttpClient的方法,它提供了设置sslContext的方法,如果没有设置则通过SSLContexts.createDefault()来创建默认的SSLContext,若hostnameVerifier为null,则创建默认的DefaultHostnameVerifier,其默认会创建HttpClientConnectionManager,使用的是maxPerRoute为2,maxTotal为20的连接池。
相关文章:
聊聊HttpClientBuilder
序 本文主要研究一下HttpClientBuilder HttpClientBuilder httpclient-4.5.10-sources.jar!/org/apache/http/impl/client/HttpClientBuilder.java public class HttpClientBuilder {public static HttpClientBuilder create() {return new HttpClientBuilder();}protected…...

MacOS - Sonoma更新了啥
1 系统介绍 苹果公司于2023年9月26日发布了macOS Sonoma 14.0正式版。名称由来不知道,可能是地名:Sonoma是一个地名,指加利福尼亚州北部索诺玛县(Sonoma County)。 2 系统重要更新 2.1 将小组件添加到桌面 速览提醒事项和临近日程等。按住Control键点…...

C++17中头文件filesystem的使用
C17引入了std::filesystem库(文件系统库, filesystem library),相关类及函数的声明在头文件filesystem中,命名空间为std::filesystem。 1.path类:文件路径相关操作,如指定的路径是否存在等,其介绍参见:http…...

「专题速递」数字人直播带货、传统行业数字化升级、远程协作中的低延时视频、地产物业中的通讯终端...
音视频技术作为企业数字化转型的核心要素之一,已在各行各业展现出广泛的应用和卓越的价值。实时通信、社交互动、高清视频等技术不仅令传统行业焕发新生,还为其在生产、管理、服务提供与维护等各个领域带来了巨大的助力,实现了生产效率和服务…...

PE格式之PE头部
1. PE头部总体组成 2. DOS MZ头 3. PE头 PE头由3部分组成: 下面分别: OptionalHeader比较大: 然后是节表, 节表有多个: PE文件头部就结束了, 最后就是节区了, 来看几段代码: ; main.asm .586 .model flat, stdcall option casemap:noneinclude windows.inc include ke…...

SLAM从入门到精通(用python实现机器人运动控制)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 在ROS下面,开发的方法很多,可以是c,可以是python。大部分接口操作类的应用,其实都可以用python来开…...
接口和抽象类有什么区别?
接口和抽象类都是用于实现抽象类型的机制: 抽象类:抽象类可以包含抽象方法(未实现的方法)和具体方法(已实现的方法)。抽象类可以有字段(成员变量),这些字段可以是具体的,也可以是抽象的。一个类只能继承一个抽象类,Java不支持多继承。抽象类可以拥有构造方法,用于初…...

基于springboot+vue的人事系统
目录 前言 一、技术栈 二、系统功能介绍 员工信息管理 考勤信息管理 考勤信息管理 下班记录管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用,作为学校以及一些培训机构,都在用信息…...

记住这份软件测试八股文还怕不能拿offer?你值得拥有
前言 2023秋招即将来临,很多同学会问软件测试面试八股文有必要背吗? 我的回答是:很有必要。你可以讨厌这种模式,但你一定要去背,因为不背你就进不了大厂。 国内的互联网面试,恐怕是现存的、最接近科举考试…...

2023年,在CSDN拥有10000粉丝有多难?
该数据来源于粉丝数人数排行前5000名用户的关注用户列表中产生的,由于采集样本数有限,数据可能具有一定的误差,仅供参考,本次采样用户数大概在100万以上。 筛选条件人数粉丝人数大于50007519粉丝人数大于100003763粉丝人数大于500…...

C++ -- 学习系列 关联式容器 set 与 map
一 关联式容器是什么? c 中有两种容器类型:关联式容器与序列式容器(顺序容器) 关联式中的容器是按照关键字来存储与访问的,序列式容器(顺序容器)则是元素在容器中的相对位置来存储与访问的。…...

Day 04 python学习笔记
Python数据容器 元组 元组的声明 变量名称(元素1,元素2,元素3,元素4…….) (元素类型可以不同) eg: tuple_01 ("hello", 1, 2,-20,[11,22,33]) print(type(tuple_01))结果&#x…...

Moonbeam Ignite强势回归
参与Moonbeam上最新的流动性计划 还记得新一轮的流动性激励计划吗?Moonbeam Ignite社区活动带着超过300万枚GLMR奖励来啦!体验新项目,顺便薅一把GLMR羊毛。 本次Moonbeam Ignite活动的参与项目均为第二批Moonbeam生态系统Grant资助提案中获…...
【改造后序遍历算法】95. 不同的二叉搜索树 II
95. 不同的二叉搜索树 II 解题思路 遍历每一个节点查看以k为根节点的二叉搜索树储存所有左子树的根节点储存所有右子树的根节点将左子树和右子树组装起来 将根节点储存在向量中 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeN…...
栈的基本操作(数据结构)
顺序栈的基本操作 #include <stdlib.h> #include <iostream> #include <stdio.h> #define MaxSize 10typedef struct{int data[MaxSize];int top; }SqStack;//初始化栈 void InitStack(SqStack &S){S.top -1; } //判断栈空 bool StackEmpty(SqStack S)…...
D. Jellyfish and Mex Codeforces Round 901 (Div. 2)
Problem - D - Codeforces 题目大意:有一个n个数的数组a,数m初始为0,每次操作可以删除任意一个数,然后m加上那个数,求n次操作和m的最小值 1<n<5000;0<a[i]<1e9 思路:可以发现&am…...

操作系统内存管理相关
1. 虚拟内存 1.1 什么是虚拟内存 虚拟内存是计算机系统内存管理的一种技术,我们可以手动设置自己电脑的虚拟内存。不要单纯认为虚拟内存只是“使用硬盘空间来扩展内存“的技术。虚拟内存的重要意义是它定义了一个连续的虚拟地址空间,并且 把内存扩展到硬…...

Sui流动性质押黑客松获胜者公布,助力资产再流通
Sui流动质押黑客松于日前结束Demo Day演示,其中有五个团队获奖、六个团队荣誉提名,共有超过30个项目获得参赛资格。此外,有两个团队赢得了Sui上DeFi协议提供的赏金。 本次黑客松的目的是挖掘并奖励将流动质押功能集成到其apps和产品中的开发…...

为什么在使用PageHelper插件时,指定的每页记录数大小失效?显示所有的记录数
1.问题现象: 这里指定每页显示5条,却把所有的记录数都显示出来了 2.分析: 之前是可以的,然后发现:PageHelper.startPage(pageNum,pageSize) 和执行sql的语句 顺序颠倒了,然后就出错了。 3.验证…...
XML文档基础
什么是XML XML (eXtensible Markup Language,可扩展标记语言) 是一种用于存储和传输数据的文本文件格式。用户可以按照XML规则自定义标记,XML 的设计目标是传输数据,而不是显示数据,因此它是一种通用的标记语言,可用于…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...