diff --git a/Git/4 远程操作.md b/Git/4 远程操作.md index cf343b5f..3cff8340 100644 --- a/Git/4 远程操作.md +++ b/Git/4 远程操作.md @@ -115,3 +115,8 @@ git push --tags ``` 将本地所有标签推送到远程仓库中 + +### 使用远程分支覆盖本地分支 +git fetch --all +git reset --hard origin/dev (这里dev要修改为对应的分支名,将本地分支只想远程分支的地提交) +git pull origin dev \ No newline at end of file diff --git a/Java三方库/apa b/Java三方库/apa new file mode 100644 index 00000000..e69de29b diff --git a/Java三方库/apache-httpcomponents.md b/Java三方库/apache-httpcomponents.md new file mode 100644 index 00000000..cfc6c541 --- /dev/null +++ b/Java三方库/apache-httpcomponents.md @@ -0,0 +1 @@ +https://hc.apache.org/ \ No newline at end of file diff --git a/Java三方库/commons-bean.md b/Java三方库/commons-bean.md new file mode 100644 index 00000000..38b1906a --- /dev/null +++ b/Java三方库/commons-bean.md @@ -0,0 +1,30 @@ +https://commons.apache.org/ +引入依赖 + + commons-beanutils + commons-beanutils + 1.9.4 + +1 +2 +3 +4 +5 +BeanUtils/BeanUtilsBean +拷贝: cloneBean/copyProperties/copyProperty +获取:getArrayProperty/getSimpleProperty/getProperty +其他操作:setProperty设置属性 populate将Bean设置到Map中 describe将Bean转成Map +1 +2 +3 +PropertyUtils类 +判断:isReadable/isWriteable +获取: + getProperty/getSimpleProperty/getPropertyType + getReadMethod/getWriteMethod/getIndexedProperty/setIndexedProperty + getMappedProperty/setMappedProperty/getNestedProperty/setNestedProperty + getPropertyDescriptor/getPropertyEditorClass +拷贝和设置:copyProperties/setProperty/setSimpleProperty /clearDescriptors +———————————————— +版权声明:本文为CSDN博主「white camel」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 +原文链接:https://blog.csdn.net/m0_37989980/article/details/126396868 \ No newline at end of file diff --git a/Java三方库/commons-collections4.md b/Java三方库/commons-collections4.md new file mode 100644 index 00000000..97b4ba3b --- /dev/null +++ b/Java三方库/commons-collections4.md @@ -0,0 +1,63 @@ +https://commons.apache.org/ +## 引入依赖 +```xml + + + org.apache.commons + commons-collections4 + 4.4 + +``` + +## CollectionUtils 集合工具类 +``` +添加/删除:addAll/addIgnoreNull/retainAll/removeAll/ +获取: + find/get/containsAny/index/size/sizeIsEmpty/select/selectRejected/subtract + typedCollection +判断: + isEmpty/isNotEmpty/isFull/exists/isEqualCollection/ + isSubCollection/isProperSubCollection +转换: + collect/transform/transformedCollection/predicatedCollection + unmodifiableCollection/synchronizedCollection +计算:cardinality/countMatches/maxSize +过滤:filter +集合:intersection/union/disjunction 交集,并集,差集 +其他操作: + reverseArray 翻转 forAllDo 给每个元素执行闭包 + getCardinalityMap 转成Map,key是元素,value是次数 +``` + +## ListUtils-List工具类 +``` +判断: isEqualList +集合:intersection/sum/union/retainAll 交集,并集,合集,差集 +操作:removeAll/hashCodeForList +子集: typedList/subtract/fixedSizeList +转换处理:synchronizedList/unmodifiableList/predicatedList/transformedList/lazyList +``` + +## SetUtils-Set集合工具类 +``` +判断:isEqualSet +转换处理: + transformedSet/transformedSortedSet/predicatedSet/predicatedSortedSet + unmodifiableSet/synchronizedSet/synchronizedSortedSet + orderedSet/typedSet/typedSortedSet +操作:hashCodeForSet +``` + +## MapUtils-Map工具类 +``` +获取:getObject/getString/getXXX/getXXXValue 获取指定类型值,getXXXValue 如果没有值则默认值 +子集:fixedSizeMap/fixedSizeSortedMap/typedMap/typedSortedMap +判断:isEmpty/isNotEmpty +转换: + predicatedMap/predicatedSortedMap/transformedMap/transformedSortedMap/ + synchronizedMap/synchronizedSortedMap/ + unmodifiableMap/unmodifiableSortedMap/multiValueMap/orderedMap + toMap/toProperties/lazyMap/lazySortedMap +添加移除:safeAddToMap/putAll +其他操作:invertMap/debugPrint/verbosePrint +``` \ No newline at end of file diff --git a/Java三方库/commons-io.md b/Java三方库/commons-io.md new file mode 100644 index 00000000..2c613e65 --- /dev/null +++ b/Java三方库/commons-io.md @@ -0,0 +1,56 @@ +https://commons.apache.org/ +## 引入依赖 +```xml + + commons-io + commons-io + 2.11.0 + +``` +## FileUtils 文件操作工具类 +``` +文件夹操作: + copyDirectory/deleteDirectory/cleanDirectory/getTempDirectory/getTempDirectoryPath + moveDirectory/moveDirectoryToDirectory/moveFileToDirectory/moveToDirectory + forceMkdir/getUserDirectory/getUserDirectoryPath +文件操作: + touch/copyFile/copyURLToFile/moveFile/deleteQuietly/forceDelete/forceDeleteOnExit + toFile/toFiles/toURLs + isFileNewer/isFileOlder + readLines/readFileToByteArray/readFileToString/lineIterator/openOutputStream + write/writeLines/writeByteArrayToFile/writeStringToFile/openInputStream +其他操作: + iterateFiles/listFiles/contentEquals/sizeOf/sizeOfDirectory +``` +## IOUtils 流操作工具类 +``` +读操作:lineIterator/read/readLines +写操作:write/writeLines +转换: toInputStream/toBufferedInputStream/toByteArray/toCharArray/toString +其他操作:copy/copyLarge/contentEquals/skip/skipFully/closeQuietly +``` +## FilenameUtils 文件名工具类 +``` +获取: + getName/getBaseName/getPrefix/getPrefixLength/getExtension + getPath/getFullPath/getFullPathNoEndSeparator/getPathNoEndSeparator +判断: + isExtension/equals/equalsNormalized/equalsOnSystem +其他操作: + removeExtension/indexOfExtension + separatorsToSystem/separatorsToUnix/separatorsToWindows + indexOfLastSeparator +``` +## 其他工具类 +``` +文件比较器: + CompositeFileComparator/DefaultFileComparator/DirectoryFileComparator + ExtensionFileComparator/LastModifiedFileComparator/NameFileComparator + PathFileComparator/PathFileComparator +文件过滤器: + AgeFileFilter/AndFileFilter/CanReadFileFilter/CanWriteFileFilter + DelegateFileFilter/DirectoryFileFilter/EmptyFileFilter/FalseFileFilter/FileFileFilter + FileFilterUtils/HiddenFileFilter/MagicNumberFileFilter/NameFileFilter/NotFileFilter + OrFileFilter/PrefixFileFilter/RegexFileFilter/SizeFileFilter/SuffixFileFilter + TrueFileFilter/WildcardFileFilter/WildcardFilter +``` \ No newline at end of file diff --git a/Java三方库/commons-lang3.md b/Java三方库/commons-lang3.md new file mode 100644 index 00000000..2b394680 --- /dev/null +++ b/Java三方库/commons-lang3.md @@ -0,0 +1,152 @@ + +## 引入依赖 +``` + + org.apache.commons + commons-lang3 + 3.12.0 + +``` +## 数据类型工具类 +### StringUtils 字符串工具类 +```java +包含判断方法:contains/containsXXX +字符串替换方法:replace/replaceXXX +获取子串:substring/substringXXX +判断方法: +1、isEmpty/isNotEmpty/isBlank/isNotBlank/isNumeric/isWhitespace +2、sartsWith/startsWithAny/endsWith/endsWithIgnoreCase +索引(index):indexOf/indexOfXXX/tIndexOf/lastIndexOfXXX +处理方法: + abbreviate 缩短 capitalise 首字母 repeat 重复 left/right/center 左右中间 + removeXXX 移除 trimXXX 去空 reverseXXX 翻转 stripXXX 移除 + defaultXXX 默认 lowerCase/upperCase deleteXXX 删除处理 + splitXXX分解处理 join 拼接 +``` + +### StringEscapeUtils 转义字符串工具类 +StringEscapeUtils类可以对html js xml sql 等代码进行转义来防止SQL注入 +``` +escapeCsv/unescapeCsv/escapeHtml/unescapeHtml/escapeJava/unescapeJava +escapeJavaScript/unescapeJavaScript/escapeXml/unescapeXml/escapeSql +``` + +### NumberUtils 数字工具类 + +``` +创建数字:createXXX 创建Integer,Float,Double,Number,BigDecimal,BigInteger等数字 +字符转数字:toXXX 字符串转数字:Byte,Double,Float,Int,Long,Short +判断是否数字:isDigits/isNumber +其他方法:compare,max,min, +``` + +### ArrayUtils 数组工具类 + +``` +添加移除:add,addAll,remove,removeElement, +拷贝:clone +判断:contains,isEmpty,isNotEmpty,isEquals,isSameLength, +其他:getLength,indexOf,lastIndexOf,nullToEmpty,reverse,subArray, +转换:toMap,toObject,toPrimitive,toString +``` +### EnumUtils 枚举工具类 +``` +getEnum/getEnumIgnoreCase/getEnumList/getEnumMap +iterator +``` +## 随机数工具类 +### RandomUtils 随机数工具类 +``` +nextBoolean/nextInt/nextLong/nextFloat/nextDouble +``` + +### RandomStringUtils 随机字符串工具类 +``` +random/randomNumeric/randomAlphabetic/randomAscii +``` +## 日期时间工具类 +### DateUtils 日期工具类 +``` +说明:XXX表示milisecends,seconds,minutes,hours,days,weeks,months,years +时间加减:add/addXXX +时间设置:setXXX +获取片段:getFragmentInXXX 获取date的1月1日0点0分0秒到指定时间的片段值 +判断: isSameDay/isSameInstant/isSameLocalTime +转换: parseDate/parseDateStrictly +取模: ceiling/round/truncate +时间段:iterator 注意rangeStyle=1到4表示周范围以及偏移,5和6表示月偏移 +``` + +### DateFormatUtils时间格式化 +``` +格式化:format/formatUTC +``` +### DurationFormatUtils时间段格式化 +``` +formatDuration/formatDurationHMS/formatDurationISO +formatPeriod/formatPeriodISO +formatDurationWords +``` + +### StopWatch 秒表 +``` +start/stop/suspend/split/resume/reset/unsplit +getSplitTime/getStartTime/getTime/ +toSplitString/toString +``` + + +## 反射工具类 + +### ClassUtils 类工具 +``` +获取: + 1、类和接口 :getClass/getAllInterfaces/getAllSuperclasses/getShortClassName + 2、包:getPackageName/getPackageCanonicalName + 3、方法:getPublicMethod +转换: + 1、toClass/convertClassesToClassNames/convertClassNamesToClasses/ + 2、primitivesToWrappers/primitiveToWrapper/wrappersToPrimitives/wrapperToPrimitive +判断:isAssignable/isInnerClass +``` + +### MethodUtils +``` +getAccessibleMethod/getMatchingAccessibleMethod +invokeMethod/invokeStaticMethod/invokeExactMethod/invokeExactStaticMethod +``` + +### FieldUtils +``` +getField/readField/writeField +getDeclaredField/readDeclaredField/writeDeclaredField +readDeclaredStaticField/readStaticField/writeDeclaredStaticField/writeStaticField +``` + +### ConstructorUtils +``` +getAccessibleConstructor/getMatchingAccessibleConstructor +invokeConstructor/invokeExactConstructor +``` + +## ObjectUtils 对象工具类 +``` +max/min/toString/identityToString/appendIdentityToString/defaultIfNull +``` +## SystemUtils 系统属性工具类 +``` +getJavaHome/getJavaIoTmpDir/getJavaVersion/getUserDir/getUserHome/ +isJavaAwtHeadless/isJavaVersionAtLeast +``` + +## SerializationUtils 序列化工具类 +``` +clone/deserialize/serialize +``` + +## LocaleUtils 本地工具类 +``` +availableLocaleList/availableLocaleSet +countriesByLanguage +localeLookupList/toLocale/isAvailableLocale/languagesByCountry +``` \ No newline at end of file diff --git a/Java三方库/fastjson.md b/Java三方库/fastjson.md index d3e6676f..3ce204eb 100644 --- a/Java三方库/fastjson.md +++ b/Java三方库/fastjson.md @@ -10,7 +10,9 @@ Java对象和json格式之间转换。 * jsonobject如果没有指定java对象 +https://blog.csdn.net/qq_37436172/article/details/127334627 +https://www.jianshu.com/p/f5407d45d590 ## 序列化 @@ -40,7 +42,7 @@ public abstract class JSON { ## 反序列化 -``` +```java package com.alibaba.fastjson; public abstract class JSON { @@ -62,4 +64,50 @@ public abstract class JSON { // 将JSON字符串反序列为JSONObject public static JSONObject parseObject(String text); } +``` + + +## Map泛型反序列化 +JSON串转为 Map,含有泛型的 JSON 反序列化 + +### JSON串 --> Map +```java +@Test +public void test() { + Map orderMap = new HashMap(){{ + put("001", new Order(1001L, "T001")); + put("002", new Order(1002L, "T002")); + }}; + String jsonStr = JSON.toJSONString(orderMap); + + // 没有泛型 是不安全的 + Map map = JSON.parseObject(jsonStr); + + // TypeReference 但构造方法是protected,所以使用它的子类 + // 用匿名内部类作为 TypeReference 子类 + TypeReference> typeReference = new TypeReference>() {}; + Map result = JSON.parseObject(jsonStr, typeReference); +``` +### JSON串 --> Map> + +```java +@Test +public void test() { + + Map> data = new HashMap>() {{ + put(2022001, Arrays.asList(new Order(1001L, "T001"))); + put(2022002, Arrays.asList(new Order(1002L, "T002"))); + }}; + String jsonStr = JSON.toJSONString(data); + + Map> map = JSON.parseObject(jsonStr, new TypeReference>>() {}); + + // 方式一:使用 Type + Type type = new TypeReference>>(){}.getType(); + Map> resultMap = JSON.parseObject(jsonStr, type); + + // 方式二 + Map> integerListMap = JSON.parseObject(jsonStr, new TypeReference>>() {}); + +} ``` \ No newline at end of file diff --git a/Java基础教程/JavaIO与网络编程/附录3:IO、网络编程与web开发的关系.md b/Java基础教程/JavaIO与网络编程/附录3:IO、网络编程与web开发的关系.md index aac63d79..fce1b9d7 100644 --- a/Java基础教程/JavaIO与网络编程/附录3:IO、网络编程与web开发的关系.md +++ b/Java基础教程/JavaIO与网络编程/附录3:IO、网络编程与web开发的关系.md @@ -17,7 +17,8 @@ ### web开发 以下三个是Http服务实现。技能够提供http协议的服务端,也能实现http协议的客户端。是有协议的。 -1. Servlet 最基本的http服务实现方法。采用多线程阻塞的方式。包括服务端和HttpClient,可以独立使用 -2. Java ws.rs - Resteasy 基于标准接口的http服务的实现方法。包括服务端和ResteasyClient,可以独立使用 -3. Spring MVC 基于Servlet的http服务的封装和实现方法。包括服务端和RestTemplate,可以独立使用 -4. Spring Flux 基于Netty的http服务的封装和实现方法。包括服务端和WebClient,可以独立使用 \ No newline at end of file +1. JDK&Jetty&Netty,提供了不同的socket通信方式,可以自己实现http服务的客户端和服务端 +2. apache Servlet 最基本的http服务实现方法。采用多线程阻塞的方式。包括服务端和HttpClient,可以独立使用 +3. Java ws.rs - Resteasy 基于标准接口的http服务的实现方法。包括服务端和ResteasyClient,可以独立使用 +4. Spring MVC 基于Servlet的http服务的封装和实现方法。包括服务端和RestTemplate,可以独立使用 +5. Spring Flux 基于Netty的http服务的封装和实现方法。包括服务端和WebClient,可以独立使用 \ No newline at end of file diff --git a/Java基础教程/Java实用技巧/05 Java远程调试.md b/Java基础教程/Java实用技巧/05 Java远程调试.md new file mode 100644 index 00000000..518f8dd2 --- /dev/null +++ b/Java基础教程/Java实用技巧/05 Java远程调试.md @@ -0,0 +1,64 @@ +## 1 server端 + +### 启动命令 +> 打jar包允许被远程调试 +``` +java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9091 -jar xxx.jar + +``` + +### 参数说明 + +1. transport: 指定运行的被调试应用和调试者之间的通信协议,它由几个可选值: dt_socket:主要的方式,采用socket方式连接。 dt_shmem:采用共享内存方式连接,仅支持 Windows 平台。 +2. server: 指定当前应用作为调试服务端还是客户端,默认为n。 如果你想将当前应用作为被调试应用,设置该值为 y,如果你想将当前应用作为客户端,作为调试的发起者,设置该值为n。 +3. suspend: 当前应用启动后,是否阻塞应用直到被连接,默认值为 y。 在大部分的应用场景,这个值为 n,即不需要应用阻塞等待连接。一个可能为 y的应用场景是,你的程序在启动时出现了一个故障,为了调试,必须等到调试方连接上来后程序再启动。 +4. address: 暴露的调试连接端口,默认值为 8000。 此端口一定不能与项目端口重复,且必须是服务器开放的端口。 +5. onthrow: 当程序抛出设定异常时,中断调试。 +6. onuncaught: 当程序抛出未捕获异常时,是否中断调试,默认值为 n。 +7. launch: 当调试中断时,执行的程序。 +8. timeout: 该参数限定为java -agentlib:jdwp=…可用,单位为毫秒ms。 当 suspend = y 时,该值表示等待连接的超时;当 suspend = n 时,该值表示连接后的使用超时。 + +### 参考命令 +``` +-agentlib:jdwp=transport=dt_socket,server=y,address=8000:以 Socket 方式监听 8000 端口,程序启动阻塞(suspend 的默认值为 y)直到被连接。 +-agentlib:jdwp=transport=dt_socket,server=y,address=localhost:8000,timeout=5000:以 +Socket 方式监听 8000 端口,当程序启动后 5 秒无调试者连接的话终止,程序启动阻塞(suspend 的默认值为 +y)直到被连接。 +-agentlib:jdwp=transport=dt_shmem,server=y,suspend=n:选择可用的共享内存连接地址并使用 +stdout 打印,程序启动不阻塞。 +-agentlib:jdwp=transport=dt_socket,address=myhost:8000:以 socket 方式连接到 myhost:8000上的调试程序,在连接成功前启动阻塞。 +agentlib:jdwp=transport=dt_socket,server=y,address=8000,onthrow=java.io.IOException,launch=/usr/local/bin/debugstub:以 +Socket 方式监听 8000 端口,程序启动阻塞(suspend 的默认值为 y)直到被连接。当抛出 IOException +时中断调试,转而执行 usr/local/bin/debugstub程序。 +``` + +### 直接运行Java程序允许远程调试 +命令 +``` +-Xdebug -Xrunjdwp:transport=dt_socket,address=8088,server=y,suspend=n +``` +具体参数详解: + +1. -Xdebug 通知JVM工作在DEBUG模式下; +2. -Xrunjdwp 通知JVM使用(Java debug wire protocol)运行调试环境。该参数同时包含了一系列的调试选项; +3. **transport**指定了调试数据的传送方式,dt_socket是指用SOCKET模式,另有dt_shmem指用共享内存方式,其中,dt_shmem只适用于Windows平台; +4. address 调试服务器的端口号,客户端用来连接服务器的端口号; +5. server=y/n VM 是否需要作为调试服务器执行; +6. suspend=y/n 是否在调试客户端建立连接之后启动 VM; + +## IDEA本地 + +1. 在 IDEA 中,点击 Edit Configurations,在弹框中点击 + 号,然后选择Remote。 +![](image/2023-03-01-13-43-46.png) + +2. 填写服务器的地址及端口,点击 OK 即可。 +![](image/2023-03-01-13-44-05.png) + +3. 配置完毕后,DEBUG 调试运行即可。 +![](image/2023-03-01-13-44-25.png) + +4. 配置完毕后点击保存即可,因为我配置的 suspend=n,因此服务端程序无需阻塞等待我们的连接。我们点击 IDEA 调试按钮,当我访问某一接口时,能够正常调试。 +![](image/2023-03-01-13-45-10.png) + + + diff --git a/Java基础教程/Java实用技巧/image/2023-03-01-13-43-46.png b/Java基础教程/Java实用技巧/image/2023-03-01-13-43-46.png new file mode 100644 index 00000000..13cdff90 Binary files /dev/null and b/Java基础教程/Java实用技巧/image/2023-03-01-13-43-46.png differ diff --git a/Java基础教程/Java实用技巧/image/2023-03-01-13-44-05.png b/Java基础教程/Java实用技巧/image/2023-03-01-13-44-05.png new file mode 100644 index 00000000..bf09a993 Binary files /dev/null and b/Java基础教程/Java实用技巧/image/2023-03-01-13-44-05.png differ diff --git a/Java基础教程/Java实用技巧/image/2023-03-01-13-44-25.png b/Java基础教程/Java实用技巧/image/2023-03-01-13-44-25.png new file mode 100644 index 00000000..b44a879c Binary files /dev/null and b/Java基础教程/Java实用技巧/image/2023-03-01-13-44-25.png differ diff --git a/Java基础教程/Java实用技巧/image/2023-03-01-13-45-10.png b/Java基础教程/Java实用技巧/image/2023-03-01-13-45-10.png new file mode 100644 index 00000000..a4417b77 Binary files /dev/null and b/Java基础教程/Java实用技巧/image/2023-03-01-13-45-10.png differ diff --git a/Java基础教程/Java并发编程/11 Java只执行一次.md b/Java基础教程/Java并发编程/11 Java只执行一次.md new file mode 100644 index 00000000..4cc34c72 --- /dev/null +++ b/Java基础教程/Java并发编程/11 Java只执行一次.md @@ -0,0 +1,195 @@ + +## 问题说明 + +有时我们希望java程序能在高并发操作下,某个函数只执行一次。 +1. 一般情况下,设置一个门控值,每次执行前检查是否执行过,如果没有执行过,则设置为false,并执行。如果为true则不执行。如果是单线程,该方法能够发挥作用。 +2. 多线程情况下,如果多个线程同时判断门控值,都得到true,就会同时进入执行结果。 + +## 1 高并发下的原子操作 + + + +使用一个原子Boolean值作为门控值。同一时间进入判断的值只有一个,能保证多线程情况下,该函数仍然只执行一次。 +```java + private AtomicBoolean inited = new AtomicBoolean(false); + + /** + * @see ServerManager#getServerList() + */ + @Override + public List getServerList() { + if (inited.compareAndSet(false, true)) { + initServerList(); + } + return new ArrayList(serverNodes); + } +``` + + +## 2 使用两次判断加锁 +先判断该值,然后加锁再判断执行。能够保证一下两点内容 +1. 第二次判断操作的互斥性,即第二次判断在加锁条件下执行,该判断只会在同一时间发生一次。 +2. 外层的判断能够减少执行完成后,其他的高并发访问不再加锁,提高程序的性能。 + +``` +if(value == true){ + synchronized(this){ + if(value == true){ + initMethod(); + } + } +} +``` + + +一、介绍 +AtomicBoolean是通过原子方式更新 boolean 值。AtomicBoolean用于诸如原子更新标志之类的应用程序,但是不能替换boolean类使用。 + +二、原理 +AtomicBoolean 内部持有了一个 volatile变量修饰的value, +底层通过对象在内存中的偏移量(valueOffset)对应的旧值与当前值进行比较, +相等则更新并返回true;否则返回false。 + +即CAS的交换思想. +AtomicBoolean 内部可以保证,在高并发情况下,同一时刻只有一个线程对变量修改成功。 +/** +* Atomically update Java variable to x if it is currently +* holding expected. +* @return true if successful +*/ +public final native boolean compareAndSwapInt(Object o, long offset, + int expected, + int x); +Unsafe.compareAndSwapInt()介绍 + +三、应用 +1、AtomicBoolean 示例 +public class AtomicBooleanDemo1 { + + // 设置初始化值为false,参数通过cas操作更新为true + private static AtomicBoolean initialized = new AtomicBoolean(false); + + public void init() { + if (initialized.compareAndSet(false, true)) { + // 此处只会有一个线程进入 + System.out.println(Thread.currentThread().getName() + " init success"); + } else { + System.out.println(Thread.currentThread().getName() + " cas 失败"); + } + } + + public static void main(String[] args) { + final AtomicBooleanDemo1 demo1 = new AtomicBooleanDemo1(); + + for (int i = 0; i < 100; i++) { + new Thread(new Runnable() { + public void run() { + demo1.init(); + } + }).start(); + } + + } +} +2、 使用volatile 替换 + +public class AtomicBooleanDemo2 { + + // 设置初始化值为false,通过volatile变量保证线程可见性 + private static volatile boolean initialized; + + public void init() { + if (initialized == false) { + initialized = true; + // 此处只会有一个线程进入 + System.out.println(Thread.currentThread().getName() + " init success"); + } else { + System.out.println(Thread.currentThread().getName() + " cas 失败"); + } + } + + public static void main(String[] args) throws Exception { + final AtomicBooleanDemo2 demo1 = new AtomicBooleanDemo2(); + + for (int i = 0; i < 10; i++) { + new Thread(new Runnable() { + public void run() { + demo1.init(); + } + }).start(); + } + + } +} + +针对这种boolean类型的并发操作,可以使用AtomicBoolean进行设置即可 + +三、源码分析 +public class AtomicBoolean implements java.io.Serializable { + private static final long serialVersionUID = 4654671469794556979L; + // setup to use Unsafe.compareAndSwapInt for updates + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + // 对象在内存中的映射偏移量 + private static final long valueOffset; + + + // static静态块,随AtomicBoolean 类加载时执行一次,可见valueOffset针对所有对象在内存中的映射 + // 值都是同一个 + static { + try { + valueOffset = unsafe.objectFieldOffset + (AtomicBoolean.class.getDeclaredField("value")); + } catch (Exception ex) { throw new Error(ex); } + } + + private volatile int value; + + // 构造函数,对value赋默认值 + public AtomicBoolean(boolean initialValue) { + value = initialValue ? 1 : 0; + } + + // 无参构造,value默认值为0 + public AtomicBoolean() { + } + +} +将expect和AtomicBoolean的value进行比较,若一致则更新为update,否则返回false + + /** + * Atomically sets the value to the given updated value + * if the current value {@code ==} the expected value. + * + * @param expect the expected value + * @param update the new value + * @return {@code true} if successful. False return indicates that + * the actual value was not equal to the expected value. + */ + public final boolean compareAndSet(boolean expect, boolean update) { + int e = expect ? 1 : 0; + int u = update ? 1 : 0; + // 通过unsafe的cas方法操作,比较并替换,底层通过lock前缀加锁实现原子性 + return unsafe.compareAndSwapInt(this, valueOffset, e, u); + } + +四、unsafe方法的实现原理 +1、unsafe的compareAndSet内部是如何保证原子性的? +底层通过cmpxchg汇编命令处理,如果是多处理器会使用lock前缀,可以达到内存屏障的效果,来进行隔离。 + +具体分析见 【Unsafe中的compareAndSet实现】 + + + +五、总结 +AtomicBoolean内存代码无锁,比常规的synchronized或lock锁效率较高 +既然volatile可以修饰boolean类型,为什么还需要有AtomicBoolean原子类? +CAS 都是会存在ABA问题(可采用版本号解决等) + + +补充: +A: boolean类型本身作为标记,保证了原子性,加上volatile保证了可见性,所以此处两种方式都可以,但对于int等其他类型字段volatile则不可保证原子操作,必须依赖于原子类操作等 + + AtomicBoolean可以保证原子执行,保证线程安全; + volatile 只能保证线程可见性、指令重排序等;保证不了原子性。 +boolean类型作为标记字段,本身保证了原子性 \ No newline at end of file diff --git a/Java基础教程/Java标准库/11 Unsafe类.md b/Java基础教程/Java标准库/11 Unsafe类.md new file mode 100644 index 00000000..bc2f4718 --- /dev/null +++ b/Java基础教程/Java标准库/11 Unsafe类.md @@ -0,0 +1,156 @@ +  我们在阅读JAVA并发编程中JUC包下的类源码的时候,经常看见Unsafe类,但是有一个疑惑,为什么处理并发安全的类,要起名为“不安全”呢?后来对于Unsafe深入理解之后,才知道作者的原意,这里说的不安全并不是针对于并发操作,而是指:该类对于普通程序员来说是“危险”的,一般开发者不应该也不会用到此类。因为Unsafe类功能过于强大,提供了一些可以绕开JVM的更底层的功能。它让JAVA拥有了想C语言的指针一样操作内存空间的能力,能够提升效率,但是也带来了指针的复杂性等问题,所以官方并不建议使用,并且没提供文档支持,甚至计划在高版本去除该类。 + + + +## 1 Unsafe构造及获取 + +  Unsafe类使用final修饰,不允许继承,且构造函数是private,使用了饿汉式单例,通过一个静态方法getUnsafe()来获取实例。 + +![](image/2023-03-13-10-53-12.png) + +## 2 Unsage功能概述 +![](image/2023-03-13-10-54-08.png) + +内存管理 + +  Unsafe的内存管理功能主要包括:普通读写、volatile读写、有序写入、直接操作内存等分配内存与释放内存的功能。 + +  3.1.1、普通读写 + +    Unsafe可以读写一个类的属性,即便这个属性是私有的,也可以对这个属性进行读写。 + + + + + + + +     getInt等用于从对象的指定偏移地址处读取一个值。putInt等用于在对象指定偏移地址处写入一个值。其他原始类型也提供有对应的方法。 + +    此外,Unsafe的getByte、putByte方法提供了直接在一个地址上进行读写的功能。 + +  3.1.2、volatile读写 + +    普通的读写无法保证可见性和有序性,而volatile读写就可以保证可见性和有序性;但是相对普通读写要更加昂贵。 + + + +  3.1.3、有序写入 + +    有序写入只保证写入的有序性,不保证可见性,就是说一个线程的写入不保证其他线程立马可见。 + +    而与volatile写入相比putOrderedXX写入代价相对较低,putOrderedXX写入不保证可见性,但是保证有序性,所谓有序性,就是保证指令不会重排序。 + +  3.1.4、直接操作内存 + +    Unsafe提供了直接操作内存的能力: + + + + + +    也提供了一些获取内存信息的方法:getAddress、addressSize、pageSize + +    值得注意的是:利用copyMemory方法可以实现一个通用的对象拷贝方法,无需再对每一个对象都实现clone方法,但只能做到对象浅拷贝。 + + +CAS + +  Unsafe类的CAS操作为Java的锁机制提供了一种新的解决办法,比如AtomicInteger等类都是通过该方法来实现的。compareAndSwap*方法是原子的,可以避免繁重的锁机制,提高代码效率。 + +   + +   CAS一般用于乐观锁,它在Java中有广泛的应用,ReentrantLock、ConcurrentHashMap,ConcurrentLinkedQueue等都有用到CAS来实现乐观锁。 + +3.3、偏移量 + +  Unsafe提供以下方法获取对象的指针,通过对指针进行偏移,不仅可以直接修改指针指向的数据(即使它们是私有的),甚至可以找到JVM已经认定为垃圾、可以进行回收的对象。 + + + +// 获取静态属性Field在对象中的偏移量,读写静态属性时必须获取其偏移量 +public native long staticFieldOffset(Field var1); +// 获取非静态属性Field在对象实例中的偏移量,读写对象的非静态属性时会用到这个偏移量 +public native long objectFieldOffset(Field var1); +// 返回Field所在的对象 +public native Object staticFieldBase(Field var1); +// 返回数组中第一个元素实际地址相对整个数组对象的地址的偏移量 +public native int arrayBaseOffset(Class var1); +// 计算数组中第一个元素所占用的内存空间 +public native int arrayIndexScale(Class var1); + +3.4、线程调度 + +// 唤醒线程 +public native void unpark(Object var1); + +// 挂起线程 +public native void park(boolean var1, long var2); + +// 用于加锁,已废弃 +public native void monitorEnter(Object var1); + +// 用于加锁,已废弃 +public native void monitorExit(Object var1); + +// 用于加锁,已废弃 +public native boolean tryMonitorEnter(Object var1); + +  通过park方法将线程进行挂起, 线程将一直阻塞到超时或中断条件出现。unpark方法可以终止一个挂起的线程,使其恢复正常。 + +  整个并发框架中对线程的挂起操作被封装在LockSupport类中,LockSupport类中有各种版本park方法,但最终都调用了Unsafe.park()方法。 + +3.5、类加载 + +// 方法定义一个类,用于动态地创建类 +public native Class defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6); + +// 动态的创建一个匿名内部类 +public native Class defineAnonymousClass(Class var1, byte[] var2, Object[] var3); + +// 判断是否需要初始化一个类 +public native boolean shouldBeInitialized(Class var1); + +// 保证已经初始化过一个类 +public native void ensureClassInitialized(Class var1); + + 3.6、内存屏障 + +// 保证在这个屏障之前的所有读操作都已经完成 +public native void loadFence(); + +// 保证在这个屏障之前的所有写操作都已经完成 +public native void storeFence(); + +// 保证在这个屏障之前的所有读写操作都已经完成 +public native void fullFence(); + + 3.7、非常规对象实例化 + +  通常,我们通过new或反射来实例化对象,而Unsafe类提供的allocateInstance方法,可以直接生成对象实例,且无需调用构造方法和其他初始化方法;这在对象反序列化的时候会很有用,能够重建和设置final字段,而不需要调用构造方法。 + +3.8、数组操作 + + + +  arrayBaseOffset(获取数组第一个元素的偏移地址)与arrayIndexScale(获取数组中元素的增量地址)配合起来使用,就可以定位数组中每个元素在内存中的位置。 + +  由于Java的数组最大值为Integer.MAX_VALUE,使用Unsafe类的内存分配方法可以实现超大数组。实际上这样的数据就可以认为是C数组,因此需要注意在合适的时间释放内存。 + +3.9、其他 + +  当然,Unsafe类中还提供了大量其他的方法,比如上面提到的CAS操作,以AtomicInteger为例,当我们调用getAndIncrement、getAndDecrement等方法时,本质上调用的就是Unsafe的getAndAddInt方法。 + +  如下为两个系统相关的方法: + +  // 返回系统指针的大小。返回值为4(32位系统)或 8(64位系统)。 + +  public native int addressSize(); + +  // 内存页的大小,此值为2的幂次方。 + +  public native int pageSize(); + +3.10、结语 + +  在实践的过程中,如果阅读其他框架或类库实现,当发现用到Unsafe类,可对照该类的整体功能,结合应用场景进行分析,即可大概了解其功能。 \ No newline at end of file diff --git a/Java基础教程/Java标准库/image/2023-03-13-10-53-12.png b/Java基础教程/Java标准库/image/2023-03-13-10-53-12.png new file mode 100644 index 00000000..8b13962c Binary files /dev/null and b/Java基础教程/Java标准库/image/2023-03-13-10-53-12.png differ diff --git a/Java基础教程/Java标准库/image/2023-03-13-10-54-08.png b/Java基础教程/Java标准库/image/2023-03-13-10-54-08.png new file mode 100644 index 00000000..dfe71c2b Binary files /dev/null and b/Java基础教程/Java标准库/image/2023-03-13-10-54-08.png differ diff --git a/Java基础教程/Java语言基础/23 native方法.md b/Java基础教程/Java语言基础/23 native方法.md new file mode 100644 index 00000000..1c24afa2 --- /dev/null +++ b/Java基础教程/Java语言基础/23 native方法.md @@ -0,0 +1,8 @@ +https://blog.csdn.net/weixin_43653599/article/details/111592025 + +https://www.jianshu.com/p/21f7ebb9e63f + + + + + diff --git a/Linux/Linux工具命令/printf.md b/Linux/Linux工具命令/printf.md index 29660b42..0b72bf09 100644 --- a/Linux/Linux工具命令/printf.md +++ b/Linux/Linux工具命令/printf.md @@ -35,9 +35,70 @@ arguments:一到多个参数。 ```shell 转义序列:除了支持printf(1)和printf(3)的转义序列,内建printf还支持以下转义序列: -%b 展开参数中的反斜杠转义字符。 +# 常用转义字符 +\" - 转义后的双引号 +\\ - 转义后的反斜杠 +\b - 退格符,后退 +\n - 换行符,换行 +\r - 回车符,回车 +\t - 水平制表符 +\v - 垂直制表符 +\a 警告字符,通常为ASCII的BEL字符 +\f 换页 +\ 表示\本身 + + +# 常用类型转换字符 + +%d,%i 十进制整数 +%f - 将参数打印为浮点数 +%s - 将参数打印为字符串 +%x - 将参数打印为十六进制整数 +%o - 将参数打印为八进制整数 +%b - 相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义 +%c ASCII字符,即显示对应参数的第一个字符 +%u 不带正负号的十进制值 +%x 十六进制值(a-f) +%X 十六进制值(A-F) +%% 表示%本身 %q 将参数扩起以用作shell输入。 %(fmt)T 根据strftime(3)中的转义字符来输出日期时间字符串。 + + + +\003设置字符 + +背景和字体颜色 + +字背景颜色范围: 40–49 字颜色: 30–39 +40: 黑 30: 黑 +41: 红 31: 红 +42: 绿 32: 绿 +43: 黄 33: 黄 +44: 蓝 34: 蓝 +45: 紫 35: 紫 +46: 深绿 36: 深绿 +47: 白色 37: 白色 + +\033[0m 关闭所有属性 +\033[1m 设置高亮度 +\033[4m 下划线 +\033[5m 闪烁 +\033[7m 反显 +\033[8m 消隐 +\033[30m – \033[37m 设置前景色 +\033[40m – \033[47m 设置背景色 +\033[nA 光标上移n行 +\033[nB 光标下移n行 +\033[nC 光标右移n行 +\033[nD 光标左移n行 +\033[y;xH设置光标位置 +\033[2J 清屏 +\033[K 清除从光标到行尾的内容 +\033[s 保存光标位置 +\033[u 恢复光标位置 +\033[?25l 隐藏光标 +\033[?25h 显示光标 ``` #### 返回值 @@ -187,3 +248,22 @@ value1 的`Description`段落。 + +### 一个刷新显示的脚本实例 +```sh +#!/bin/bash +# 当Ctrl+c 清空屏幕再退出,见引用3 +trap "clear;exit" 2 +# 翻一个新屏幕 +clear +# 每秒刷新输出屏幕的端口统计结果 +while [ true ] +do + # 需要执行的功能命令,各写各的业务 + report=`$*` + # 使用ASCI码控制光标定位回到第一行第一列,见引用1 + printf "\033[1;1H%s" $report + # 进程睡眠1秒 + sleep 1 +done +``` \ No newline at end of file diff --git a/test5.csv b/test5.csv new file mode 100644 index 00000000..216a9297 --- /dev/null +++ b/test5.csv @@ -0,0 +1,414 @@ +10.111.51.108,24 +10.111.67.138,24 +10.111.67.137,24 +10.111.50.3,24 +10.111.67.70,24 +10.111.67.71,24 +10.111.164.139,24 +10.111.67.132,24 +10.111.67.131,24 +10.111.164.137,24 +10.111.67.75,24 +10.111.67.72,24 +10.111.164.135,24 +10.111.164.136,24 +10.111.67.73,24 +10.111.51.101,24 +10.111.51.103,24 +10.111.51.104,24 +10.111.51.100,24 +10.111.68.171,24 +10.111.51.116,24 +10.111.164.2,24 +10.111.68.172,24 +10.111.51.119,24 +10.111.67.56,24 +10.111.67.57,24 +10.111.67.54,24 +10.111.67.55,24 +10.111.67.145,24 +10.111.164.9,24 +10.111.67.147,24 +10.111.67.58,24 +10.111.67.146,24 +10.111.67.59,24 +10.111.164.128,24 +10.111.67.143,24 +10.111.67.142,24 +10.111.67.63,24 +10.111.67.64,24 +10.111.164.127,24 +10.111.67.62,24 +10.111.164.123,24 +10.111.51.113,24 +10.111.51.114,24 +10.111.164.121,24 +10.111.68.160,24 +10.111.67.46,24 +10.111.67.49,24 +10.111.67.47,24 +10.111.67.48,24 +10.111.164.118,24 +10.111.67.52,24 +10.111.164.115,24 +10.111.164.116,24 +10.111.67.53,24 +10.111.67.51,24 +10.111.164.114,24 +10.111.68.167,24 +10.111.68.166,24 +10.111.68.153,24 +10.111.68.152,24 +10.111.68.151,24 +10.111.67.34,24 +10.111.67.35,24 +10.111.67.32,24 +10.111.67.33,24 +10.111.67.38,24 +10.111.67.39,24 +10.111.67.36,24 +10.111.67.37,24 +10.111.164.107,24 +10.111.67.42,24 +10.111.67.40,24 +10.111.68.157,24 +10.111.164.100,24 +10.111.68.156,24 +10.111.68.155,24 +10.111.68.154,24 +10.111.68.159,24 +10.111.68.158,24 +10.111.66.254,24 +10.111.164.180,24 +10.111.66.253,24 +10.111.67.29,24 +10.111.66.251,24 +10.111.67.23,24 +10.111.67.24,24 +10.111.67.21,24 +10.111.67.22,24 +10.111.67.27,24 +10.111.67.28,24 +10.111.67.25,24 +10.111.67.26,24 +10.111.67.174,24 +10.111.67.170,24 +10.111.65.217,24 +10.111.67.30,24 +10.111.65.216,24 +10.111.67.31,24 +10.111.67.171,24 +10.111.66.255,24 +10.111.50.236,24 +10.111.50.235,24 +10.111.67.16,24 +10.111.65.222,24 +10.111.65.221,24 +10.111.67.15,24 +10.111.65.224,24 +10.111.65.223,24 +10.111.67.184,24 +10.111.65.226,24 +10.111.67.186,24 +10.111.65.225,24 +10.111.65.228,24 +10.111.65.227,24 +10.111.67.183,24 +10.111.65.229,24 +10.111.67.182,24 +10.111.51.129,24 +10.111.67.156,24 +10.111.67.155,24 +10.111.67.157,24 +10.111.67.154,24 +10.111.51.123,24 +10.111.51.124,24 +10.111.51.125,24 +10.111.68.196,24 +10.111.68.195,24 +10.111.67.167,24 +10.111.67.166,24 +10.111.67.169,24 +10.111.67.168,24 +10.111.67.163,24 +10.111.67.165,24 +10.111.67.164,24 +10.111.65.206,24 +10.111.65.205,24 +10.111.65.208,24 +10.111.65.207,24 +10.111.164.145,24 +10.111.164.140,24 +10.111.51.130,24 +10.111.51.131,24 +10.111.164.141,24 +10.111.51.132,24 +10.111.164.47,24 +10.111.164.46,24 +10.111.169.246,24 +10.111.169.242,24 +10.111.68.109,24 +10.111.68.108,24 +10.111.68.107,24 +10.111.169.248,24 +10.111.68.228,24 +10.111.68.102,24 +10.111.68.225,24 +10.111.68.101,24 +10.111.68.226,24 +10.111.68.227,24 +10.111.68.220,24 +10.111.68.106,24 +10.111.68.221,24 +10.111.68.105,24 +10.111.68.222,24 +10.111.68.104,24 +10.111.68.103,24 +10.111.68.223,24 +10.111.164.58,24 +10.111.164.59,24 +10.111.169.251,24 +10.111.169.252,24 +10.111.169.253,24 +10.111.68.217,24 +10.111.68.218,24 +10.111.68.219,24 +10.111.68.213,24 +10.111.68.215,24 +10.111.68.216,24 +10.111.68.210,24 +10.111.68.211,24 +10.111.68.212,24 +10.111.164.22,24 +10.111.164.23,24 +10.111.68.206,24 +10.111.68.207,24 +10.111.68.208,24 +10.111.164.29,24 +10.111.51.94,24 +10.111.164.197,24 +10.111.51.95,24 +10.111.164.198,24 +10.111.68.205,24 +10.111.164.195,24 +10.111.164.196,24 +10.111.51.97,24 +10.111.68.201,24 +10.111.164.191,24 +10.111.164.32,24 +10.111.164.190,24 +10.111.164.31,24 +10.111.164.34,24 +10.111.164.185,24 +10.111.96.155,24 +10.111.96.153,24 +10.111.6.8,24 +10.111.51.81,24 +10.111.96.150,24 +10.111.169.201,24 +10.111.68.145,24 +10.111.68.144,24 +10.111.68.143,24 +10.111.96.159,24 +10.111.96.145,24 +10.111.164.14,24 +10.111.51.90,24 +10.111.68.131,24 +10.111.96.143,24 +10.111.68.130,24 +10.111.164.13,24 +10.111.169.213,24 +10.111.67.101,24 +10.111.67.100,24 +10.111.169.218,24 +10.111.68.135,24 +10.111.68.134,24 +10.111.51.82,24 +10.111.68.133,24 +10.111.68.132,24 +10.111.68.139,24 +10.111.68.138,24 +10.111.96.148,24 +10.111.51.89,24 +10.111.68.137,24 +10.111.96.149,24 +10.111.68.136,24 +10.111.68.241,24 +10.111.68.120,24 +10.111.68.129,24 +10.111.68.124,24 +10.111.68.246,24 +10.111.68.247,24 +10.111.68.121,24 +10.111.96.137,24 +10.111.96.138,24 +10.111.68.245,24 +10.111.163.24,24 +10.111.67.209,24 +10.111.67.202,24 +10.111.68.119,24 +10.111.68.118,24 +10.111.68.235,24 +10.111.68.113,24 +10.111.68.112,24 +10.111.68.236,24 +10.111.68.237,24 +10.111.68.111,24 +10.111.68.238,24 +10.111.68.110,24 +10.111.68.117,24 +10.111.68.231,24 +10.111.68.116,24 +10.111.68.115,24 +10.111.68.114,24 +10.111.68.234,24 +10.111.23.212,24 +10.111.6.74,24 +10.111.167.232,24 +10.111.23.213,24 +10.111.167.235,24 +10.111.23.215,24 +10.111.96.194,24 +10.111.96.191,24 +10.111.96.190,24 +10.111.167.230,24 +10.111.96.188,24 +10.111.96.185,24 +10.111.167.229,24 +10.111.96.179,24 +10.111.96.177,24 +10.111.96.178,24 +10.111.96.174,24 +10.111.169.185,24 +10.111.23.202,24 +10.111.169.194,24 +10.111.162.186,24 +10.111.169.195,24 +10.111.96.164,24 +10.111.167.248,24 +10.111.23.203,24 +10.111.96.163,24 +10.111.169.191,24 +10.111.23.204,24 +10.111.96.160,24 +10.111.96.161,24 +10.111.23.207,24 +10.111.23.208,24 +10.111.164.88,24 +10.111.164.83,24 +10.111.164.84,24 +10.111.164.98,24 +10.111.164.99,24 +10.111.164.96,24 +10.111.164.97,24 +10.111.164.91,24 +10.111.164.94,24 +10.111.164.95,24 +10.111.164.92,24 +10.111.67.0,24 +10.111.67.4,24 +10.111.67.6,24 +10.111.67.5,24 +10.111.67.8,24 +10.111.67.7,24 +10.111.67.9,24 +10.111.167.210,24 +10.111.167.213,24 +10.111.167.214,24 +10.111.164.67,24 +10.111.167.216,24 +10.111.164.60,24 +10.111.167.218,24 +10.111.167.219,24 +10.111.164.76,24 +10.111.164.74,24 +10.111.167.200,24 +10.111.167.201,24 +10.111.167.202,24 +10.111.164.78,24 +10.111.167.204,24 +10.111.164.73,24 +10.111.167.206,24 +10.111.167.207,24 +10.111.167.208,24 +10.111.167.209,24 +10.111.167.198,24 +10.111.170.44,24 +10.111.167.190,24 +10.111.167.196,24 +10.111.167.197,24 +10.111.170.42,24 +10.111.170.43,24 +10.111.167.187,24 +10.111.167.188,24 +10.111.167.189,24 +10.111.170.27,24 +10.111.50.247,24 +10.111.50.248,24 +10.111.50.246,24 +10.111.65.231,24 +10.111.50.243,24 +10.111.50.244,24 +10.111.65.230,24 +10.111.50.242,24 +10.111.65.234,24 +10.111.50.249,24 +client_address,24 +10.111.50.250,24 +10.111.170.35,24 +10.111.170.33,24 +10.111.170.34,24 +10.111.68.88,24 +10.111.68.89,24 +10.111.68.94,24 +10.111.68.95,24 +10.111.68.96,24 +10.111.68.90,24 +10.111.68.77,24 +10.111.68.82,24 +10.111.68.83,24 +10.111.22.81,24 +10.111.68.87,24 +10.111.22.80,24 +10.111.68.84,24 +10.111.170.13,24 +10.111.170.11,24 +10.111.68.67,24 +10.111.68.71,24 +10.111.22.73,24 +10.111.68.72,24 +10.111.68.75,24 +10.111.68.76,24 +10.111.164.201,24 +10.111.68.74,24 +10.111.164.202,24 +10.111.164.200,24 +10.111.167.176,24 +10.111.167.177,24 +10.111.23.199,24 +10.111.68.57,24 +10.111.68.58,24 +10.111.68.56,24 +10.111.167.173,24 +10.111.68.59,24 +10.111.167.174,24 +10.111.167.175,24 +10.111.68.60,24 +10.111.68.61,24 +10.111.68.64,24 +10.111.68.65,24 +10.111.68.62,24 +10.111.67.78,24 +10.111.68.46,24 +10.111.67.79,24 +10.111.68.47,24 +10.111.67.76,24 +10.111.67.77,24 +10.111.68.45,24 +10.111.68.48,24 +10.111.67.80,24 +10.111.68.53,24 +10.111.68.54,24 +10.111.67.175,23 +10.111.164.3,20 +10.111.164.33,1 \ No newline at end of file diff --git a/计算机网络/3.4 传输层-TCP.md b/计算机网络/3.4 传输层-TCP.md index 2e0cb870..00308996 100644 --- a/计算机网络/3.4 传输层-TCP.md +++ b/计算机网络/3.4 传输层-TCP.md @@ -67,6 +67,8 @@ TCP首部,它通常是20个字节。 * CLOSED状态不是一个真正的状态,而是这个状态图的假想起点和终点。 * 只有当SYN_RCVD状态是从LISTEN状态(正常情况)进入,而不是从SYN_SENT状态(同时打开)进入时,从SYN_RCVD回到LISTEN的状态变迁才是有效的。这意味着如果我们执行被动关闭(进入LISTEN),收到一个SYN,发送一个带ACK的SYN(进入SYN_RCVD),然后收到一个RST,而不是一个ACK,便又回到LISTEN状态并等待另一个连接请求的到来。 +![](image/2023-03-10-14-11-26.png) + ### 状态迁移图说明 1. 2MSL等待状态 @@ -153,3 +155,46 @@ RST标志表示复位,用来复位连接。 * RST的接收方会区分另一端执行的是异常关闭还是正常关闭。并可以通知应用程序。 +### TimeWait状态 +https://zhuanlan.zhihu.com/p/523678245 + +主动关闭放 + +如果我们来做个类比的话,TIME_WAIT的出现,对应的是你的程序里的异常处理,它的出现,就是为了解决网络的丢包和网络不稳定所带来的其他问题: + +第一,防止前一个连接【五元组,我们继续以 180.172.35.150:45678, tcp, 180.97.33.108:80 为例】上延迟的数据包或者丢失重传的数据包,被后面复用的连接【前一个连接关闭后,此时你再次访问百度,新的连接可能还是由180.172.35.150:45678, tcp, 180.97.33.108:80 这个五元组来表示,也就是源端口凑巧还是45678】错误的接收(异常:数据丢了,或者传输太慢了),参见下图: + + + +![](image/2023-03-10-14-25-57.png) + + + +SEQ=3的数据包丢失,重传第一次,没有得到ACK确认 +如果没有TIME_WAIT,或者TIME_WAIT时间非常端,那么关闭的连接【180.172.35.150:45678, tcp, 180.97.33.108:80 的状态变为了CLOSED,源端口可被再次利用】,马上被重用【对180.97.33.108:80新建的连接,复用了之前的随机端口45678】,并连续发送SEQ=1,2 的数据包 +此时,前面的连接上的SEQ=3的数据包再次重传,同时,seq的序号刚好也是3(这个很重要,不然,SEQ的序号对不上,就会RST掉),此时,前面一个连接上的数据被后面的一个连接错误的接收 +第二,确保连接方能在时间范围内,关闭自己的连接。其实,也是因为丢包造成的,参见下图: + +![](image/2023-03-10-14-26-19.png) + +主动关闭方关闭了连接,发送了FIN; +被动关闭方回复ACK同时也执行关闭动作,发送FIN包;此时,被动关闭的一方进入LAST_ACK状态 +主动关闭的一方回去了ACK,主动关闭一方进入TIME_WAIT状态; +但是最后的ACK丢失,被动关闭的一方还继续停留在LAST_ACK状态 +此时,如果没有TIME_WAIT的存在,或者说,停留在TIME_WAIT上的时间很短,则主动关闭的一方很快就进入了CLOSED状态,也即是说,如果此时新建一个连接,源随机端口如果被复用,在connect发送SYN包后,由于被动方仍认为这条连接【五元组】还在等待ACK,但是却收到了SYN,则被动方会回复RST +造成主动创建连接的一方,由于收到了RST,则连接无法成功 +所以,你看到了,TIME_WAIT的存在是很重要的,如果强制忽略TIME_WAIT,还是有很高的机率,造成数据粗乱,或者短暂性的连接失败。 + + +### CloseWait +被动关闭方。 + +CLOSE_WAIT才可怕,因为CLOSE_WAIT很多,表示说要么是你的应用程序写的有问题,没有合适的关闭socket;要么是说,你的服务器CPU处理不过来(CPU太忙)或者你的应用程序一直睡眠到其它地方(锁,或者文件I/O等等),你的应用程序获得不到合适的调度时间,造成你的程序没法真正的执行close操作。 + + +### 关于主动关闭和被动关闭的讨论 +请求的发起方和接收方都可能主动关闭或者被动关闭。与请求发出方和接收方无关。 + +例如,服务器响应超时,客户端等不及了,会触发超时时间主动关闭,此时虽然服务器收到了fin包,并且协议层可以返回ack进行确认,进入了closewait状态。但是服务器因为还在处理超时的任务,肯定要继续等待任务处理完成才会调用close函数,主动关闭。 + + diff --git a/计算机网络/image/2023-03-10-14-11-26.png b/计算机网络/image/2023-03-10-14-11-26.png new file mode 100644 index 00000000..54328dfd Binary files /dev/null and b/计算机网络/image/2023-03-10-14-11-26.png differ diff --git a/计算机网络/image/2023-03-10-14-25-57.png b/计算机网络/image/2023-03-10-14-25-57.png new file mode 100644 index 00000000..d613d909 Binary files /dev/null and b/计算机网络/image/2023-03-10-14-25-57.png differ diff --git a/计算机网络/image/2023-03-10-14-26-19.png b/计算机网络/image/2023-03-10-14-26-19.png new file mode 100644 index 00000000..82c337ea Binary files /dev/null and b/计算机网络/image/2023-03-10-14-26-19.png differ