不错!SpringBoot发布Jar包优化瘦身指南!

概要说明

随着Spring Boot的流行,大家体验到只需构建输出一个jar文件,然后只需一个java -jar命令就能部署运行应用的爽快。常见一些单体应用随着项目规模的扩展单个jar文件的大小越来越大,动辄两三百MB。如果再引入微服务架构,动辄一二十个微服务,所有模块jar加起来整个系统光部署文件就一两个GB。

一个系统一旦上线运行,无论新需求迭代还是Bug修复,免不了需要做部署更新,尤其对于一些交付类型项目,首次部署或异地更新, 动不动就需要传输几百MB或几个GB的部署文件,确实是一个让人头疼的问题。

可以想象一下,线上系统发现一个紧急严重Bug捅到了主管那里,交代马上紧急修复解决,研发同事火速分析排查分分钟搞定提交代码并完成构建打包并交付给运维。过一会领导着急上火来过问问题更新解决了吗?运维只能很尴尬的回答:还没呢,部署包文件比较大,正在上传有点慢...

一听领导就火了,就改了几行代码,部署更新为啥要上传几百MB的文件呢?难道没有办法优化一下吗?

遇到这样的情况,建议你往下看,或许能找到你想要的答案。

本文内容包括:

  • 如何把一两百MB的单一Spring Boot jar文件,分离为依赖组件lib目录和一个业务jar来进行部署,优化单个jar文件大小到一两百KB。。

  • 如何把一二十个微服务高度重叠的依赖组件合并到单一lib目录和多个一两百KB的业务jar来进行部署,优化整个项目部署文件大小从一两个GB大小到两三百MB。

本文内容不包括:

  • 不包括进行Spring Boot配置文件分离相关,一般简单采用通过指定active profile从外部yaml配置文件覆盖jar文件中配置即可或是采用Nacos等配置服务模式。

  • 不包括Maven最佳实践用法,列入样例工程中出于演示方便的考虑比如把一些本应放到各个Boot模块特定的配置声明直接放到顶层的parent中定义,请注意按实际情况优化调整使用。

  • 不包括可执行jar的运行模式支持参考,文中实现方式主要面向java -jar运行模式。

瘦身打怪升级过程

Level 0:常规的Fat Jar构建

参考项目目录:package-optimize-level0

主要配置:

<build><finalName>${project.artifactId}</finalName><!--特别注意:项目仅仅是为了演示配置方便,直接在parent的build部分做了插件配置和运行定义。但是实际项目中需要把这些定义只放到spring boot模块项目(可优化使用pluginManagement形式),避免干扰其他util、common等模块项目--><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

配置输出:

cd package-optimize-level0
mvn clean installls -lh package-optimize-app1/target/package-optimize-app1.jar
-rw-r--r--  1 lixia  wheel    16M Feb 24 21:06 package-optimize-app1/target/package-optimize-app1.jarjava -jar package-optimize-app1/target/package-optimize-app1.jar

重点说明:

  • (当前演示应用仅依赖了spring-boot-starter-web极少组件,所有构建输出只有十来MB)实际情况单一构建根据项目依赖组件量输出jar一般在几十MB到一两百MB甚至更大。

  • 假如有十来个微服务需要部署,那就意味着需要传输一两个GB的文件,耗时可想而知。就算是单一更新个别微服务也需要传输一两百MB。

Level 1:常见的依赖jar分离构建方式

参考项目目录:package-optimize-level1

关解决问题:

  • 降低单个微服务jar的文件大小,以便部署过程秒传文件。

主要配置:

重点配置说明请详见如下注释说明:

<build><finalName>${project.artifactId}</finalName><!--特别注意:项目仅仅是为了演示配置方便,直接在parent的build部分做了插件配置和运行定义。但是实际项目中需要把这些定义只放到spring boot模块项目(可优化使用pluginManagement形式),避免干扰其他util、common等模块项目--><plugins><!-- 拷贝项目所有依赖jar文件到构建lib目录下 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><executions><execution><id>copy-dependencies</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>${project.build.directory}/lib</outputDirectory><excludeTransitive>false</excludeTransitive><stripVersion>false</stripVersion><silent>true</silent></configuration></execution></executions></plugin><!-- Spring Boot模块jar构建 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><includes><!-- 不存在的include引用,相当于排除所有maven依赖jar,没有任何三方jar文件打入输出jar --><include><groupId>null</groupId><artifactId>null</artifactId></include></includes><layout>ZIP</layout></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins>
</build>

配置输出:

cd package-optimize-level1
mvn clean installls -lh package-optimize-app1/target/package-optimize-app1.jar
-rw-r--r--  1 lixia  wheel   149K Feb 24 20:56 package-optimize-app1/target/package-optimize-app1.jarjava -jar -Djava.ext.dirs=lib package-optimize-app1/target/package-optimize-app1.jar

实现效果:

  • 单一构建根据项目依赖组件量输出jar一般仅有一两百KB,基本可以做到秒传。

  • 这个是网上可见最常见的优化方案,还值得继续深入:假如有十来个微服务,每个服务一个jar和一个lib目录文件,首次部署也差不多需要传输一两个GB文件。

Level 2:合并所有模块依赖jar到同一个lib目录

参考项目目录:package-optimize-level2

解决问题:

  • 合并所有模块依赖jar到同一个lib目录,一般由于各模块项目依赖jar重叠程度很高,合并所有服务部署文件总计大小基本也就两三百MB

  • 但是如果采用-Djava.ext.dirs=lib加载所有jar到每个JVM,一来每个JVM都完整加载了所有jar耗费资源,二来各微服务组件版本不同会出现版本冲突问题

主要配置:

重点配置说明请详见如下注释说明:

<build><finalName>${project.artifactId}</finalName><!--特别注意:项目仅仅是为了演示配置方便,直接在parent的build部分做了插件配置和运行定义。但是实际项目中需要把这些定义只放到spring boot模块项目(可优化使用pluginManagement形式),避免干扰其他util、common等模块项目--><plugins><!-- 基于maven-jar-plugin插件实现把依赖jar定义写入输出jar的META-INFO/MANIFEST文件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><configuration><archive><manifest><addClasspath>true</addClasspath><classpathPrefix>lib/</classpathPrefix><useUniqueVersions>false</useUniqueVersions></manifest></archive></configuration></plugin><!-- 拷贝项目所有依赖jar文件到构建lib目录下 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><executions><execution><id>copy-dependencies</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><!--各子模块按照实际层级定义各模块对应的属性值,检查所有微服务模块依赖jar文件合并复制到同一个目录详见各子模块中 boot-jar-output 属性定义--><outputDirectory>${boot-jar-output}/lib</outputDirectory><excludeTransitive>false</excludeTransitive><stripVersion>false</stripVersion><silent>false</silent></configuration></execution></executions></plugin><!-- Spring Boot模块jar构建 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><includes><!-- 不存在的include引用,相当于排除所有maven依赖jar,没有任何三方jar文件打入输出jar --><include><groupId>null</groupId><artifactId>null</artifactId></include></includes><layout>ZIP</layout><!--基于maven-jar-plugin输出微服务jar文件进行二次spring boot重新打包文件的输出目录所有微服务构建输出jar文件统一输出到与lib同一个目录,便于共同引用同一个lib目录详见各子模块中boot-jar-output属性定义--><!--  --><outputDirectory>${boot-jar-output}</outputDirectory></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins>
</build>

所有lib目录文件及各微服务构建jar聚合到devops公共目录。

微服务jar文件中的META-INFO/MANIFEST文件中会生成根据模块依赖组件列表的Class-Path属性, 从而避免了不同版本jar:

Class-Path: lib/spring-boot-starter-web-2.4.3.jar lib/spring-boot-starter-2.4.3.jar lib/spring-boot-2.4.3.jar lib/spring-boot-autoconfigure-2.4.3.jar lib/spring-boot-starter-logging-2.4.3.jar lib/logback-classic-1.2.3.jar lib/logback-core-1.2.3.jar lib/slf4j-api-1.7.30.jar lib/log4j-to-slf4j-2.13.3.jar lib/log4j-api-2.13.3.jar lib/jul-to-slf4j-1.7.30.jarlib/jakarta.annotation-api-1.3.5.jar lib/spring-core-5.3.4.jar lib/spring-jcl-5.3.4.jar lib/snakeyaml-1.27.jar lib/spring-boot-starter-json-2.4.3.jar lib/jackson-databind-2.11.4.jar lib/jackson-annotations-2.11.4.jar lib/jackson-core-2.11.4.jar lib/jackson-datatype-jdk8-2.11.4.jar lib/jackson-datatype-jsr310-2.11.4.jar lib/jackson-module-parameter-names-2.11.4.jar lib/spring-boot-starter-tomcat-2.4.3.jar lib/tomcat-embed-core-9.0.43.jar lib/jakarta.el-3.0.3.jar lib/tomcat-embed-websocket-9.0.43.jar lib/spring-web-5.3.4.jar lib/spring-beans-5.3.4.jar lib/spring-webmvc-5.3.4.jar lib/spring-aop-5.3.4.jar lib/spring-context-5.3.4.jar lib/spring-expression-5.3.4.jar

配置输出:

cd package-optimize-level2
mvn clean installls -lh devops/
total 912
drwxr-xr-x  34 lixia  wheel   1.1K Feb 24 22:27 lib
-rw-r--r--   1 lixia  wheel   150K Feb 24 22:31 package-optimize-app1.jar
-rw-r--r--   1 lixia  wheel   149K Feb 24 22:31 package-optimize-app2.jar
-rw-r--r--   1 lixia  wheel   149K Feb 24 22:31 package-optimize-app3.jarjava -jar devops/package-optimize-app1.jar

实现效果:

  • 启动过程不再需要 -Djava.ext.dirs=lib 参数定义。

  • 所有微服务jar引用所有项目合并依赖组件的公共目录,部署文件总计大小一般在两三百MB。

  • 通过定制每个微服务jar文件中的META-INFO/MANIFEST文件中的Class-Path明确指明依赖版本组件类,解决各微服务不同组件版本冲突问题。

Level 3:支持system引入的非官方的三方依赖组件

参考项目目录:package-optimize-level3

解决问题:

  • 有些非官方三方的诸如sdk jar,一种做法是提交到Maven本地私服中去引用,那和普通依赖jar处理相同;但是在没有maven私服的情况下,常见的简化做法都是直接在项目中放置依赖jar然后在pom中以system scope方式定义。

  • 对于在pom中是以systemPath方式引入的,maven-jar-plugin组件没有直接参数声明包含指定scope的组件, 如果不做特殊处理META-INFO/MANIFEST中不会出现这些scope定义的组件,导致运行时类找不到。

主要配置:

重点配置说明请详见如下注释说明:

<build><finalName>${project.artifactId}</finalName><!--特别注意:项目仅仅是为了演示配置方便,直接在parent的build部分做了插件配置和运行定义。但是实际项目中需要把这些定义只放到spring boot模块项目(可优化使用pluginManagement形式),避免干扰其他util、common等模块项目--><plugins><!-- 基于maven-jar-plugin插件实现把依赖jar定义写入输出jar的META-INFO/MANIFEST文件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><configuration><archive><manifest><addClasspath>true</addClasspath><classpathPrefix>lib/</classpathPrefix><useUniqueVersions>false</useUniqueVersions></manifest><manifestEntries><!--有些非官方三方的诸如sdk jar在pom中是以systemPath方式引入的,maven-jar-plugin组件没有直接参数声明包含指定scope的组件通过使用额外定义 Class-Path 值来追加指定依赖组件列表,在子模块按实际情况指定 jar-manifestEntries-classpath 值即可例如(注意前面个点字符及各空格分隔符):. lib/xxx-1.0.0.jar lib/yyy-2.0.0.jar详见各子模块中 boot-jar-output 属性定义示例--><Class-Path>${jar-manifestEntries-classpath}</Class-Path></manifestEntries></archive></configuration></plugin><!-- 拷贝项目所有依赖jar文件到构建lib目录下 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><executions><execution><id>copy-dependencies</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><!--各子模块按照实际层级定义各模块对应的属性值,检查所有微服务模块依赖jar文件合并复制到同一个目录详见各子模块中 boot-jar-output 属性定义--><outputDirectory>${boot-jar-output}/lib</outputDirectory><excludeTransitive>false</excludeTransitive><stripVersion>false</stripVersion><silent>false</silent></configuration></execution></executions></plugin><!-- Spring Boot模块jar构建 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><includes><!-- 不存在的include引用,相当于排除所有maven依赖jar,没有任何三方jar文件打入输出jar --><include><groupId>null</groupId><artifactId>null</artifactId></include></includes><layout>ZIP</layout><!--基于maven-jar-plugin输出微服务jar文件进行二次spring boot重新打包文件的输出目录所有微服务构建输出jar文件统一输出到与lib同一个目录,便于共同引用同一个lib目录详见各子模块中boot-jar-output属性定义--><!--  --><outputDirectory>${boot-jar-output}</outputDirectory></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins>
</build>

子模块主要配置:

    <properties><!-- 按各模块实际目录层次定义相对数据,使所有服务模块输出资源汇聚到相同目录 --><boot-jar-output>../devops</boot-jar-output><!--有些供应商的sdk jar在pom中是以systemPath方式引入的,maven-jar-plugin组件没有直接参数声明包含指定scope的组件通过使用额外定义 Class-Path 值来追加指定依赖组件列表,按实际情况指定 jar-manifestEntries-classpath 值即可例如(注意前面个点字符及各空格分隔符,lib后面部分是 artifactId-version.jar 格式而不是实际文件名):. lib/xxx-1.0.0.jar lib/yyy-2.0.0.jar--><jar-manifestEntries-classpath>. lib/hik-sdk-1.0.0.jar</jar-manifestEntries-classpath></properties><dependencies><!-- 以相对路径方式定义非官方三方依赖组件 --><dependency><groupId>com.hik</groupId><artifactId>hik-sdk</artifactId><version>1.0.0</version><scope>system</scope><systemPath>${project.basedir}/lib/hik-sdk-1.0.0.jar</systemPath></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

微服务输出jar文件中的META-INFO/MANIFEST文件中会生成根据模块依赖组件列表的Class-Path属性, 最前面会追加 jar-manifestEntries-classpath 属性定义值:

Class-Path: . lib/hik-sdk-1.0.0.jar lib/spring-boot-starter-web-2.4.3.jar lib/spring-boot-starter-2.4.3.jar lib/spring-boot-2.4.3.jar lib/spring-boot-autoconfigure-2.4.3.jar lib/spring-boot-starter-logging-2.4.3.jar lib/logback-classic-1.2.3.jar lib/logback-core-1.2.3.jar lib/slf4j-api-1.7.30.jar lib/log4j-to-slf4j-2.13.3.jar lib/log4j-api-2.13.3.jar lib/jul-to-slf4j-1.7.30.jar lib/jakarta.annotation-api-1.3.5.jar lib/spring-core-5.3.4.jar lib/spring-jcl-5.3.4.jar lib/snakeyaml-1.27.jar lib/spring-boot-starter-json-2.4.3.jar lib/jackson-databind-2.11.4.jar lib/jackson-annotations-2.11.4.jar lib/jackson-core-2.11.4.jar lib/jackson-datatype-jdk8-2.11.4.jar lib/jackson-datatype-jsr310-2.11.4.jar lib/jackson-module-parameter-names-2.11.4.jar lib/spring-boot-starter-tomcat-2.4.3.jar lib/tomcat-embed-core-9.0.43.jar lib/jakarta.el-3.0.3.jar lib/tomcat-embed-websocket-9.0.43.jar lib/spring-web-5.3.4.jar lib/spring-beans-5.3.4.jar lib/spring-webmvc-5.3.4.jar lib/spring-aop-5.3.4.jar lib/spring-context-5.3.4.jar lib/spring-expression-5.3.4.jar

配置输出:

cd package-optimize-level3
mvn clean installls -lh devops/
total 912
drwxr-xr-x  36 lixia  wheel   1.1K Feb 24 23:14 lib
-rw-r--r--@  1 lixia  wheel   150K Feb 24 23:14 package-optimize-app1.jar
-rw-r--r--   1 lixia  wheel   150K Feb 24 23:14 package-optimize-app2.jar
-rw-r--r--   1 lixia  wheel   150K Feb 24 23:14 package-optimize-app3.jarjava -jar devops/package-optimize-app1.jar

最终实现效果

  • 所有服务的依赖组件合并到一个目录,总计大小在两三百MB,首次部署传输效率明显提速。

  • 各微服务jar一两百KB大小,日常紧急修复Bug更新个别jar基本就是瞬间秒传。

  • 各微服务jar中各自定义依赖指定版本组件列表,不会出现组件不同版本加载冲突问题。

  • 非官方的三方依赖组件也能正常引用处理。

特别提示

上述通过部署组件分离处理后,日常更新只需要传输一两百KB的业务jar文件即可。但是如果某个项目的maven依赖组件做了变更配置,则需要注意把变更的jar文件要同步到公共的lib目录。

最小化变更jar文件的小技巧:可以把构建部署资源目录提交到GIT库,以后每次版本发布同时commit到GIT库, 通过提交视图可以清晰的识别出lib目录下和业务jar本次版本发布的变更文件清单,包括微服务jar和依赖jar变更文件,以此最小化传输文件。

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

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

相关文章

Jsp中使用数据库连接池

1. 在tomcat服务器目录下面的conf中找到一个叫Context.xml的配置文件&#xff0c;在其中加入以下代码 <Resource name"jdbc/books"auth"Container" type"javax.sql.DataSource"maxActive"100"maxIdle"30"maxWait"10…

Java IdentityHashMap values()方法与示例

IdentityHashMap类values()方法 (IdentityHashMap Class values() method) values() method is available in java.util package. values()方法在java.util包中可用。 values() method is used to return the values exist in this IdentityHashMap to be viewed in a Collecti…

CountDownLatch:别浪,等人齐再团!

一入王者深似海&#xff0c;从此对象是路人。哈喽观众老爷们大家好&#xff0c;我是战神吕布字奉先&#xff0c;今天给大家来一部吕布的教学视频&#xff01;咳咳&#xff0c;不对。大家好&#xff0c;我是磊哥&#xff0c;今天给大家来一篇 CountDownLatch 的文章。在开始之前…

ASP在 Web.config 中创建数据库连接字符串

在 Web.config 中创建数据库连接串我们需要在网站的配置文件中增加一些行&#xff0c;以便 Entity Framework 知道如何连接到我们的数据库&#xff0c;双击Web.config 文件。 卷到文件的最后&#xff0c;然后增加一个 <connectionStrings> 的配置节&#xff0c;如何所示&…

easyUI layout 中使用tabs+iframe解决请求两次方法

demo中的事例在加载tab页面时是 1 function createFrame(url) {2 var s <iframe name"iframepanel" scrolling"no" frameborder"0" src" url " style"width:100%;height:100%;"></iframe>;3 …

jQuery 的选择器 元素选择器

>> 转&#xff1a;http://www.cnblogs.com/onlys/articles/jQuery.htmljQuery 的选择器可谓之强大无比&#xff0c;这里简单地总结一下常用的元素查找方法 $("#myELement") 选择id值等于myElement的元素&#xff0c;id值不能重复在文档中只能有一个id值是my…

Java FilterInputStream skip()方法与示例

FilterInputStream类skip()方法 (FilterInputStream Class skip() method) skip() method is available in java.io package. skip()方法在java.io包中可用。 skip() method is used to skip the given number of bytes of data from this FilterInputStream. skip()方法用于从…

附彩蛋|Spring Security 竟然故意延长登录时间?知道真相的我惊呆了!

2011年12月21日&#xff0c;有人在网络上公开了一个包含600万个CSDN用户资料的数据库&#xff0c;数据全部为明文储存&#xff0c;包含用户名、密码以及注册邮箱。事件发生后CSDN在微博、官方网站等渠道发出了声明&#xff0c;解释说此数据库系2009年备份所用&#xff0c;因不明…

DirectX 矩阵

基础&#xff1a; 下标&#xff1a;第一个下标为该元素所在行的索引&#xff0c;第二个下标为该元素所在列的索引。如下图所示 行向量和列向量&#xff1a;只有单行的向量称为行向量&#xff0c;只有单列的称之为列向量。 相等 维数和元素都相等 数乘(与标量相乘) 每一个元素与…

div 图片滚动 / 文字滚动

今天研究了一下图片滚动&#xff0c;网上有很多可以使用的例子&#xff0c;所以先是找了一个用的是表格布局的&#xff0c;如下&#xff1a;<!DOCTYPE html> <html xmlns"http://www.w3.org/1999/xhtml"> <head><meta http-equiv"Content-…

为什么阿里内部不允许用Executors创建线程池?

来源&#xff1a;cnblogs.com/zjfjava/p/11227456.html1. 通过Executors创建线程池的弊端在创建线程池的时候&#xff0c;大部分人还是会选择使用Executors去创建。下面是创建定长线程池&#xff08;FixedThreadPool&#xff09;的一个例子&#xff0c;严格来说&#xff0c;当使…

Java FilePermission暗含()方法与示例

FilePermission类implies()方法 (FilePermission Class implies() method) implies() method is available in java.io package. implies()方法在java.io包中可用。 implies() method is used to check whether this FilePermission implies the given permission (perm) or no…

填充

1. $number 68 {0:d7} -f $number2. $number1 68$number1.PadLeft(7,0)转载于:https://www.cnblogs.com/IvanChen/p/4492976.html

RabbitMQ中7种消息队列和保姆级代码演示!

blog.csdn.net/qq_32828253/article/details/110450249七种模式介绍与应用场景简单模式&#xff08;Hello World&#xff09;做最简单的事情&#xff0c;一个生产者对应一个消费者&#xff0c;RabbitMQ相当于一个消息代理&#xff0c;负责将A的消息转发给B应用场景&#xff1a;…

如何在使用ASPMVC4的分部视图中获取数据展示

如何在使用ASPMVC4的分部视图中获取数据展示在ASPMVC4中&#xff0c;创建的网站项目会用到分部视图&#xff0c;通过Html.Partial("视图名")来加载到页面上&#xff1b;但是如何把数据附加到分部视图中在加载到主页上&#xff0c;是个新的问题。暂时发现这个问题有两…

Java枚举getDeclaringClass()方法与示例

枚举类getDeclaringClass()方法 (Enum Class getDeclaringClass() method) getDeclaringClass() method is available in java.lang package. getDeclaringClass()方法在java.lang包中可用。 getDeclaringClass() method is used to return the Class object denoting the enum…

项目已被os x使用 不能打开-黑苹果之路

之前复制了几个视频文件到NTFS的盘上&#xff0c;在mac中始终无法使用&#xff08;甚至是chmod&#xff09;&#xff0c;无论是哪种播放软件&#xff0c;甚至改成dmg类型都无法打开&#xff0c;报“项目已被os x使用 不能打开”&#xff0c;用ls命令发现文件属性中多了个标志&a…

CyclicBarrier:人齐了,老司机就发车了!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;上一篇咱讲了 CountDownLatch 可以解决多个线程同步的问题&#xff0c;相比于 join 来说它的应用范围更广&#xff0c;不仅可…

Leetcode 2975. Maximum Square Area by Removing Fences From a Field

Leetcode 2975. Maximum Square Area by Removing Fences From a Field 1. 解题思路2. 代码实现 题目链接&#xff1a;2975. Maximum Square Area by Removing Fences From a Field 1. 解题思路 这一题思路上是比较直接的&#xff0c;就是直接求出横向和纵向上可能的interva…

判断ip是否合法

//用来判断ip是否合法public boolean checkIp(String tempIp) {String regex "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)){3}";Pattern p Pattern.compile(regex);Matcher m p.matcher(tempIp);return m.matches();}