From 226469dac3547e4c3d0a89084abc94109e4449d6 Mon Sep 17 00:00:00 2001 From: fybug <1006291762@qq.com> Date: Tue, 11 Feb 2025 16:45:13 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=AE=8C=E6=88=90=EF=BC=8C?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 50 +- build.gradle | 153 ++- gradle/wrapper/gradle-wrapper.properties | 3 +- jar/PDConcurrent_bin.jar | Bin 15481 -> 14946 bytes jar/PDConcurrent_sources.jar | Bin 11899 -> 11929 bytes .../fybug/nulll/pdconcurrent/ObjLock.java | 236 +++-- .../java/fybug/nulll/pdconcurrent/RWLock.java | 497 +++++---- .../java/fybug/nulll/pdconcurrent/ReLock.java | 261 +++-- .../java/fybug/nulll/pdconcurrent/SyLock.java | 986 +++++++++--------- .../fybug/nulll/pdconcurrent/e/LockType.java | 12 +- .../nulll/pdconcurrent/fun/tryConsumer.java | 58 +- .../nulll/pdconcurrent/fun/tryFunction.java | 36 +- .../nulll/pdconcurrent/fun/tryRunnable.java | 112 +- .../nulll/pdconcurrent/fun/trySupplier.java | 36 +- .../nulll/pdconcurrent/package-info.java | 2 +- src/test/java/a.java | 29 - 16 files changed, 1240 insertions(+), 1231 deletions(-) delete mode 100644 src/test/java/a.java diff --git a/README.md b/README.md index 49817e3..f387e90 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,12 @@ ![Gradle 8.10.2](https://img.shields.io/badge/Gradle-8.10.2-04303b.svg "tool") ![Apache 2](https://img.shields.io/badge/license-Apache%202-blue.svg "License") --- [Java Doc](https://apidoc.gitee.com/fybug/PDConcurrent) -- +[//]: # (-- [Java Doc](https://apidoc.gitee.com/fybug/PDConcurrent) --) --- [项目主页](https://fybug.gitee.io/projectsby/PDConcurrent.html) -- +[//]: # (-- [项目主页](https://fybug.gitee.io/projectsby/PDConcurrent.html) --) ------------------------------------------------------------------------------- -**专注于单个功能,无附加bug** - ## 简介 轻量级,高可靠,易学习的并发管理工具。 @@ -24,12 +22,15 @@ 如果你已经熟悉 java 的多线程管理,尤其是 ReentrantReadWriteLock 读写锁的话你会更容易学会本工具。 -本工具采用读写锁标准,无论内部实现如何,外部接口均提供 **read, **write 方法区分读锁并发域和写锁并发域 +无论内部实现如何,外部接口均提供 **read, **write 方法区分读锁并发域和写锁并发域 ### 基础使用示例 + ```java -public static void main(String[] args) { - var lock = SyLock.newObjLock(); +public final SyLock lock = SyLock.newObjLock(); + +public static +void main(String[] args) { lock.read(() -> { // 并发域代码内容 [return null;]? // 可选择是否返回 @@ -46,10 +47,13 @@ public static void main(String[] args) { 可通过接口的工厂方法实例化内部采用不同实现的锁。 ### synchronized 锁 + ```java -public static void main(String[] args) { +public final SyLock lock = SyLock.newObjLock(); + +public static +void main(String[] args) { // 使用 - var lock = SyLock.newObjLock(); lock.read(() -> { // 并发域代码内容 }); @@ -63,10 +67,16 @@ public static void main(String[] args) { ``` ### ReentrantLock 锁 + +支持使用`newCondition()`获取`Condition`对象 + +支持通过`isLocked()`检查是否被占用 + ```java -public static void main(String[] args) { +public static +void main(String[] args) { // 使用 - var lock = SyLock.newReLock(); + SyLock lock = SyLock.newReLock(); lock.read(() -> { // 并发域代码内容 }); @@ -83,10 +93,18 @@ public static void main(String[] args) { ``` ### ReadWriteLock 锁 + +支持通过`toread()`进行写锁 => 读锁降级 + +支持使用`newReadCondition()` `newWriteCondition()`获取`Condition`对象 + +支持通过`isLocked()` `isWriteLocked()` `isReadLocked()`检查是否被占用 + ```java -public static void main(String[] args) { +public static +void main(String[] args) { // 使用 - var lock = SyLock.newRWLock(); + SyLock lock = SyLock.newRWLock(); lock.read(() -> { // 并发域代码内容 }); @@ -103,17 +121,19 @@ public static void main(String[] args) { ``` ## 使用方法 + 请导入其 `jar` 文件,文件在 **发行版** 或项目的 **jar** 文件夹下可以找到 -> PDConcurrent.jar 为不包含源码的包 +> PDConcurrent_bin.jar 为编译包 > -> PDConcurrent_sources.jar 为仅包含源码的包 +> PDConcurrent_sources.jar 为源码包 **发行版中可以看到全部版本
项目下的 jar 文件夹是当前最新的每夜版** 可通过 **WIKI** 或者 **doc文档** 深入学习本工具 ## 分支说明 + **dev-master**:当前的开发分支,可以拿到最新的每夜版 jar **releases**:当前发布分支,稳定版的源码 diff --git a/build.gradle b/build.gradle index 37a7b5a..bceb435 100644 --- a/build.gradle +++ b/build.gradle @@ -1,116 +1,113 @@ plugins { - id 'java' - id 'idea' + id 'java' + id 'idea' } tasks.withType(JavaCompile).configureEach { - options.encoding = "UTF-8" + options.encoding = "UTF-8" } group 'fybug.nulll' version = '0.1.0' java { - toolchain { - languageVersion = JavaLanguageVersion.of(23) - } + toolchain { + languageVersion = JavaLanguageVersion.of(23) + } } repositories { - mavenLocal() - mavenCentral() - google() - maven { url 'https://maven.aliyun.com/repository/releases' } - maven { url "https://maven.aliyun.com/repository/jcenter" } - maven { url "https://maven.aliyun.com/repository/mapr-public" } - maven { url "https://maven.aliyun.com/repository/staging-alpha" } - maven { url "https://maven.aliyun.com/repository/central" } - maven { url "https://maven.aliyun.com/repository/public/" } - maven { url "https://maven.aliyun.com/repository/google" } - maven { url "https://maven.aliyun.com/repository/gradle-plugin" } - maven { url "https://maven.aliyun.com/repository/spring" } - maven { url "https://maven.aliyun.com/repository/spring-plugin" } - maven { url "https://maven.aliyun.com/repository/grails-core" } - maven { url "https://maven.aliyun.com/repository/snapshots" } - maven { url "https://maven.aliyun.com/repository/apache-snapshots" } - maven { url "https://maven.aliyun.com/repository/staging-alpha-group" } + mavenLocal() + mavenCentral() + google() + maven { url 'https://maven.aliyun.com/repository/releases' } + maven { url "https://maven.aliyun.com/repository/jcenter" } + maven { url "https://maven.aliyun.com/repository/mapr-public" } + maven { url "https://maven.aliyun.com/repository/staging-alpha" } + maven { url "https://maven.aliyun.com/repository/central" } + maven { url "https://maven.aliyun.com/repository/public/" } + maven { url "https://maven.aliyun.com/repository/google" } + maven { url "https://maven.aliyun.com/repository/gradle-plugin" } + maven { url "https://maven.aliyun.com/repository/spring" } + maven { url "https://maven.aliyun.com/repository/spring-plugin" } + maven { url "https://maven.aliyun.com/repository/grails-core" } + maven { url "https://maven.aliyun.com/repository/snapshots" } + maven { url "https://maven.aliyun.com/repository/apache-snapshots" } + maven { url "https://maven.aliyun.com/repository/staging-alpha-group" } } dependencies { - // 本地依赖 - implementation fileTree(dir: 'lib', includes: ['*.jar']) + // 本地依赖 + implementation fileTree(dir: 'lib', includes: ['*.jar']) - // 注释包 - compileOnly "jakarta.validation:jakarta.validation-api:+" - compileOnly "jakarta.annotation:jakarta.annotation-api:+" - // lombok - compileOnly 'org.projectlombok:lombok:+' - annotationProcessor 'org.projectlombok:lombok:+' + // 注释包 + compileOnly "jakarta.validation:jakarta.validation-api:+" + compileOnly "jakarta.annotation:jakarta.annotation-api:+" + // lombok + compileOnly 'org.projectlombok:lombok:+' + annotationProcessor 'org.projectlombok:lombok:+' - // 注释包 - testCompileOnly "jakarta.validation:jakarta.validation-api:+" - testCompileOnly "jakarta.annotation:jakarta.annotation-api:+" - // lombok - testCompileOnly "org.projectlombok:lombok:+" - testAnnotationProcessor "org.projectlombok:lombok:+" - // testImplementation "junit:junit" + // 注释包 + testCompileOnly "jakarta.validation:jakarta.validation-api:+" + testCompileOnly "jakarta.annotation:jakarta.annotation-api:+" + // lombok + testCompileOnly "org.projectlombok:lombok:+" + testAnnotationProcessor "org.projectlombok:lombok:+" + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } test { - useJUnitPlatform() + dependencies { + testImplementation "org.junit.platform:junit-platform-launcher" + } + useJUnitPlatform() } /** 清单文件内容 */ tasks.withType(Jar).configureEach { - manifest { - attributes('Manifest-Version': '1.0', - 'Built-By': 'fybug/风雨bu改', - 'Build-Jdk-Spec': 23, - 'Bundle-Description': 'java并发控制工具', - 'Bundle-Name': 'PDConcurrent', - // 'Bundle-DocURL': 'https://apidoc.gitee.com/fybug/PDConcurrent/', - 'Bundle-Vendor': 'IntelliJ IDEA', - 'Bundle-Version': version, - 'Bundle-License': 'https://www.apache.org/licenses/LICENSE-2.0', - 'Created-By': 'Gradle 8.10.2') - } + destinationDirectory = file('jar') + manifest { + attributes('Manifest-Version': '1.0', + 'Built-By': 'fybug/风雨bu改', + 'Build-Jdk-Spec': 23, + 'Bundle-Description': 'java并发控制工具', + 'Bundle-Name': 'PDConcurrent', + // 'Bundle-DocURL': 'https://apidoc.gitee.com/fybug/PDConcurrent/', + 'Bundle-Vendor': 'IntelliJ IDEA', + 'Bundle-Version': version, + 'Bundle-License': 'https://www.apache.org/licenses/LICENSE-2.0', + 'Created-By': 'Gradle 8.10.2') + } } /** 编译包 */ tasks.register('PDConcurrent_bin', Jar) { - dependsOn classes - destinationDirectory = file('jar') - archiveFileName = 'PDConcurrent_bin.jar' - archiveClassifier = '' - // 打包编译输出 - from sourceSets.main.output + archiveFileName = 'PDConcurrent_bin.jar' + archiveClassifier = '' + // 打包编译输出 + from sourceSets.main.output } /** 源码包 */ tasks.register('PDConcurrent_sources', Jar) { - dependsOn classes - destinationDirectory = file('jar') - archiveFileName = 'PDConcurrent_sources.jar' - archiveClassifier = 'sources' - // 打包源码 - from sourceSets.main.allSource + archiveFileName = 'PDConcurrent_sources.jar' + archiveClassifier = 'sources' + // 打包源码 + from sourceSets.main.allSource } -tasks.register('PDConcurrent_all', Jar) { - dependsOn classes - destinationDirectory = file('jar') - archiveFileName = 'PDConcurrent_all.jar' - archiveClassifier = 'all' - // 打包编译输出 - from sourceSets.main.output - from { - // implementation 相关的引入解压并打包入新的jar中 - configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } - } -} +//tasks.register('PDConcurrent_all', Jar) { +// archiveFileName = 'PDConcurrent_all.jar' +// archiveClassifier = 'all' +// // 打包编译输出 +// from sourceSets.main.output +// from { +// // implementation 相关的引入解压并打包入新的jar中 +// configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } +// } +//} tasks.register('release') { - dependsOn clean - dependsOn PDConcurrent_bin - dependsOn PDConcurrent_sources + dependsOn PDConcurrent_bin + dependsOn PDConcurrent_sources } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72..e0dfef4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.10.2-bin.zip +#distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/jar/PDConcurrent_bin.jar b/jar/PDConcurrent_bin.jar index 3e78b12bf035f2071850f0ea33c68fc1d9007403..b8cac15ec28adeb50b1b857d8b05d8a9bfd79d90 100644 GIT binary patch delta 8093 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 delta 8632 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 diff --git a/jar/PDConcurrent_sources.jar b/jar/PDConcurrent_sources.jar index ecd6bd634795df52c186da40841d6dc8dc4d9469..faaffcee6bc8121a4c9264a801a03ab9485cee1a 100644 GIT binary patch delta 9545 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 E0Sgn*$p8QV delta 9490 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 diff --git a/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java b/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java index d36d99e..9f138ec 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java @@ -13,14 +13,14 @@ import lombok.Getter; *

* 使用并发管理: * {@snippet lang = java: + * public final SyLock lock = new ObjLock(); * public static void main(String[] args) { - * var lock = new ObjLock(); * lock.read(() -> System.out.println("asd")); * }} * 不使用: * {@snippet lang = java: + * public final Object lock = new Object(); * public static void main(String[] args) { - * Object lock = new Object(); * synchronized ( lock ){ * System.out.println("asd"); * } @@ -34,125 +34,123 @@ import lombok.Getter; @Getter public class ObjLock implements SyLock { - /** 作为锁的对象 */ - private final Object LOCK; + /** 作为锁的对象 */ + private final Object LOCK; - /** - * 构建并发管理 - *

- * 使用一个新的{@link Object} - */ - public - ObjLock() { this(new Object()); } + /** + * 构建并发管理 + *

+ * 使用一个新的{@link Object} + */ + public + ObjLock() { this(new Object()); } - /** - * 构建并发管理 - * - * @param lock 用作锁的对象 - * - * @since 0.1.0 - */ - public - ObjLock(@NotNull Object lock) { LOCK = lock; } + /** + * 构建并发管理 + * + * @param lock 用作锁的对象 + * + * @since 0.1.0 + */ + public + ObjLock(@NotNull Object lock) { LOCK = lock; } - //---------------------------------------------------------------------------------------------- + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param catchby {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @implNote 使用 {@code synchronized( Object )} 实现的隐式并发域 + * @see SyLock#lock(LockType, trySupplier, Function, Function) + * @since 0.1.0 + */ + @Override + public + R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, + @Nullable Function finaby) + { + R o = null; + // 不上锁 + if ( lockType == LockType.NOLOCK ) { + try { + // 主要内容 + o = run.get(); + } catch ( Exception e ) { + // 异常处理 + if ( catchby != null ) + o = catchby.apply(e); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } else { + // 上锁 + synchronized ( LOCK ){ + try { + // 主要内容 + o = run.get(); + } catch ( Exception e ) { + // 异常处理 + if ( catchby != null ) + o = catchby.apply(e); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } + } + return o; + } - /** - * {@inheritDoc} - * - * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param catchby {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} - * - * @return {@inheritDoc} - * - * @implNote 使用 {@code synchronized( Object )} 实现的隐式并发域 - * @see SyLock#lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - @Override - public - R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, - @Nullable Function finaby) - { - R o = null; - // 不上锁 - if ( lockType == LockType.NOLOCK ) { - try { - // 主要内容 - o = run.get(); - } catch ( Exception e ) { - // 异常处理 - if ( catchby != null ) - o = catchby.apply(e); - } finally { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } - } else { - // 上锁 - synchronized ( LOCK ){ - try { - // 主要内容 - o = run.get(); - } catch ( Exception e ) { - // 异常处理 - if ( catchby != null ) - o = catchby.apply(e); - } finally { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } - } - } - return o; - } - - /** - * {@inheritDoc} - * - * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} - * - * @return {@inheritDoc} - * - * @implNote 使用 {@code synchronized( Object )} 实现的隐式并发域 - * @see SyLock#trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - @Override - public - R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { - R o = null; - // 不上锁 - if ( lockType == LockType.NOLOCK ) { - try { - // 主要内容 - o = run.get(); - } finally { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } - } else { - // 上锁 - synchronized ( LOCK ){ - try { - // 主要内容 - o = run.get(); - } finally { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } - } - } - return o; - } + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @implNote 使用 {@code synchronized( Object )} 实现的隐式并发域 + * @see SyLock#trylock(LockType, trySupplier, Function) + * @since 0.1.0 + */ + @Override + public + R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { + R o = null; + // 不上锁 + if ( lockType == LockType.NOLOCK ) { + try { + // 主要内容 + o = run.get(); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } else { + // 上锁 + synchronized ( LOCK ){ + try { + // 主要内容 + o = run.get(); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } + } + return o; + } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/RWLock.java b/src/main/java/fybug/nulll/pdconcurrent/RWLock.java index 6cc7255..e5ef8d5 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/RWLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/RWLock.java @@ -17,8 +17,8 @@ import lombok.Getter; *

* 使用并发管理: * {@snippet lang = java: + * public final SyLock lock = new RWLock(); * public static void main(String[] args) { - * var lock = new RWLock(); * // 使用读锁 * lock.read(() -> System.out.println("adsa")); * // 使用写锁 @@ -27,14 +27,14 @@ import lombok.Getter; * 不使用: * {@snippet lang = java: * import java.util.concurrent.locks.ReentrantReadWriteLock; + * public final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); * public static void main(String[] args) { - * var lock = new ReentrantReadWriteLock(); * // 使用读锁 * try { * lock.readLock().lock(); * System.out.println("adsa"); * } finally { - * lock.readLock().unlock(); + * lock.readLock().unlock(); * } * // 使用写锁 * try { @@ -57,264 +57,261 @@ import lombok.Getter; @Getter public class RWLock implements SyLock { - /** 锁 */ - private final ReentrantReadWriteLock LOCK; - /** 读锁 */ - private final ReentrantReadWriteLock.ReadLock Read_LOCK; - /** 写锁 */ - private final ReentrantReadWriteLock.WriteLock Write_LOCK; - /** - * 每个线程的锁状态记录 - *

- * 读锁为{@code 1}
- * 写锁为{@code 2} - */ - private final ThreadLocal LOCK_STATE = new ThreadLocal<>(); + /** 锁 */ + private final ReentrantReadWriteLock LOCK; + /** 读锁 */ + private final ReentrantReadWriteLock.ReadLock Read_LOCK; + /** 写锁 */ + private final ReentrantReadWriteLock.WriteLock Write_LOCK; + /** + * 每个线程的锁状态记录 + *

+ * 不上锁为{@code null}
+ * 读锁为{@code 1}
+ * 写锁为{@code 2} + */ + private final ThreadLocal LOCK_STATE = new ThreadLocal<>(); - /** - * 构建并发管理 - *

- * 使用非公平锁 - */ - public - RWLock() { this(false); } + /** + * 构建并发管理 + *

+ * 使用非公平锁 + */ + public + RWLock() { this(false); } - /** - * 构造并发处理 - * - * @param fair 是否使用公平锁 - */ - public - RWLock(boolean fair) { this(new ReentrantReadWriteLock(fair)); } + /** + * 构造并发处理 + * + * @param fair 是否使用公平锁 + */ + public + RWLock(boolean fair) { this(new ReentrantReadWriteLock(fair)); } - /** - * 构造并发处理 - * - * @param lock 使用的锁 - * - * @since 0.1.0 - */ - public - RWLock(@NotNull ReentrantReadWriteLock lock) { - LOCK = lock; - Read_LOCK = LOCK.readLock(); - Write_LOCK = LOCK.writeLock(); - } + /** + * 构造并发处理 + * + * @param lock 使用的锁 + * + * @since 0.1.0 + */ + public + RWLock(@NotNull ReentrantReadWriteLock lock) { + LOCK = lock; + Read_LOCK = LOCK.readLock(); + Write_LOCK = LOCK.writeLock(); + } - //---------------------------------------------------------------------------------------------- + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param catchby {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @implNote 使用 {@link ReentrantReadWriteLock} 实现的并发域,上锁通过{@link #tolock(LockType)}进行 + * @see SyLock#lock(LockType, trySupplier, Function, Function) + * @see #tolock(LockType) + * @see #tounlock() + * @since 0.1.0 + */ + @Override + public + R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, + @Nullable Function finaby) + { + R o = null; + // 清空当前线程的状态 + LOCK_STATE.remove(); + // 防止finally内的回调抛异常 + try { + try { + // 上锁 + tolock(lockType); + // 主要内容 + o = run.get(); + } catch ( Exception e ) { + // 异常处理 + if ( catchby != null ) + o = catchby.apply(e); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } finally { + // 解锁 + tounlock(); + } + return o; + } - /** - * {@inheritDoc} - * - * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param catchby {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} - * - * @return {@inheritDoc} - * - * @implNote 使用 {@link ReentrantReadWriteLock} 实现的并发域,上锁通过{@link #tolock(LockType)}进行 - * @see SyLock#lock(LockType, trySupplier, Function, Function) - * @see #tolock(LockType) - * @see #tounlock() - * @since 0.1.0 - */ - @Override - public - R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, - @Nullable Function finaby) - { - R o = null; - // 清空当前线程的状态 - LOCK_STATE.remove(); - try { - // 上锁 - tolock(lockType); - // 主要内容 - o = run.get(); - } catch ( Exception e ) { - // 异常处理 - if ( catchby != null ) - o = catchby.apply(e); - } finally { - // 防止错误 - try { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } finally { - // 解锁 - tounlock(); - } - } - return o; - } + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @implNote 使用 {@link ReentrantReadWriteLock} 实现的并发域,上锁通过{@link #tolock(LockType)}进行 + * @see SyLock#trylock(LockType, trySupplier, Function) + * @see #tolock(LockType) + * @see #tounlock() + * @since 0.1.0 + */ + @Override + public + R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { + R o = null; + // 清空当前线程的状态 + LOCK_STATE.remove(); + // 防止finally内的回调抛异常 + try { + try { + // 上锁 + tolock(lockType); + // 主要内容 + o = run.get(); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } finally { + // 解锁 + tounlock(); + } + return o; + } - /** - * {@inheritDoc} - * - * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} - * - * @return {@inheritDoc} - * - * @implNote 使用 {@link ReentrantReadWriteLock} 实现的并发域,上锁通过{@link #tolock(LockType)}进行 - * @see SyLock#trylock(LockType, trySupplier, Function) - * @see #tolock(LockType) - * @see #tounlock() - * @since 0.1.0 - */ - @Override - public - R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { - R o = null; - // 清空当前线程的状态 - LOCK_STATE.remove(); - try { - // 上锁 - tolock(lockType); - // 主要内容 - o = run.get(); - } finally { - // 防止错误 - try { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } finally { - // 解锁 - tounlock(); - } - } - return o; - } + /** + * 根据指定类型上锁 + *

+ * 使用了可中断的上锁操作{@link ReentrantReadWriteLock.ReadLock#lockInterruptibly()}和{@link ReentrantReadWriteLock.WriteLock#lockInterruptibly()}
+ * 同时更新{@link #LOCK_STATE}记录 + * + * @param lockType 锁类型 + * + * @throws InterruptedException 上锁过程中被中断 + * @see #LOCK_STATE + * @see LockType + * @since 0.1.0 + */ + private + void tolock(@NotNull LockType lockType) throws InterruptedException { + if ( lockType != LockType.NOLOCK ) { + if ( lockType == LockType.READ ) { + // 读锁 + Read_LOCK.lockInterruptibly(); + LOCK_STATE.set((short) 1); + } else if ( lockType == LockType.WRITE ) { + // 写锁 + Write_LOCK.lockInterruptibly(); + LOCK_STATE.set((short) 2); + } + } + } - /** - * 根据指定类型上锁 - *

- * 使用了可中断的上锁操作{@link ReentrantReadWriteLock.ReadLock#lockInterruptibly()}和{@link ReentrantReadWriteLock.WriteLock#lockInterruptibly()}
- * 同时更新{@link #LOCK_STATE}记录 - * - * @param lockType 锁类型 - * - * @throws InterruptedException 上锁过程中被中断 - * @see #LOCK_STATE - * @see LockType - * @since 0.1.0 - */ - private - void tolock(@NotNull LockType lockType) throws InterruptedException { - if ( lockType != LockType.NOLOCK ) { - if ( lockType == LockType.READ ) { - // 读锁 - Read_LOCK.lockInterruptibly(); - LOCK_STATE.set((short) 1); - } else { - // 写锁 - Write_LOCK.lockInterruptibly(); - LOCK_STATE.set((short) 2); - } - } - } + /** + * 根据状态解锁 + *

+ * 根据{@link #LOCK_STATE}的状态调用对应的解锁动作
+ * 成功后清空{@link #LOCK_STATE}内容 + * + * @see #LOCK_STATE + * @since 0.1.0 + */ + private + void tounlock() { + // 根据实际状态解锁 + if ( LOCK_STATE.get() == 1 ) + Read_LOCK.unlock(); + else if ( LOCK_STATE.get() == 2 ) + Write_LOCK.unlock(); + // 清除记录数据 + LOCK_STATE.remove(); + } - /** - * 根据状态解锁 - *

- * 根据{@link #LOCK_STATE}的状态调用对应的解锁动作
- * 成功后清空{@link #LOCK_STATE}内容 - * - * @see #LOCK_STATE - * @since 0.1.0 - */ - private - void tounlock() { - // 根据实际状态解锁 - if ( LOCK_STATE.get() == 1 ) - Read_LOCK.unlock(); - else if ( LOCK_STATE.get() == 2 ) - Write_LOCK.unlock(); - // 清除记录数据 - LOCK_STATE.remove(); - } + /** + * 转为读锁 + *

+ * 如果当前状态为写锁则会降级为读锁,否则不进行操作 + * + * @return 是否成功降级 + * + * @see #LOCK_STATE + * @since 0.1.0 + */ + public + boolean toread() { + // 转为读锁 + if ( LOCK_STATE.get() == 2 ) { + Read_LOCK.lock(); + Write_LOCK.unlock(); + LOCK_STATE.set((short) 1); + return true; + } + return false; + } - /** - * 转为读锁 - *

- * 如果当前状态为写锁则会降级为读锁,否则不进行操作 - * - * @return 是否成功降级 - * - * @see #LOCK_STATE - * @since 0.1.0 - */ - public - boolean toread() { - // 转为读锁 - if ( LOCK_STATE.get() == 2 ) { - Read_LOCK.lock(); - Write_LOCK.unlock(); - LOCK_STATE.set((short) 1); - return true; - } - return false; - } + /** + * 检查锁是否被占用 + * + * @return 是否被占用 + * + * @since 0.1.0 + */ + public + boolean isLocked() { return isReadLocked() || isWriteLocked(); } - //---------------------------------------------------------------------------------------------- + /** + * 检查读锁是否被占用 + * + * @return 是否被占用 + * + * @since 0.1.0 + */ + public + boolean isReadLocked() { return LOCK_STATE.get() == 1; } - /** - * 检查锁是否被占用 - * - * @return 是否被占用 - * - * @since 0.1.0 - */ - public - boolean isLocked() { return LOCK_STATE.get() != null && (LOCK_STATE.get() == 1 || LOCK_STATE.get() == 2); } + /** + * 检查写锁是否被占用 + * + * @return 是否被占用 + * + * @since 0.1.0 + */ + public + boolean isWriteLocked() { return LOCK_STATE.get() == 2; } - /** - * 检查读锁是否被占用 - * - * @return 是否被占用 - * - * @since 0.1.0 - */ - public - boolean isReadLocked() { return LOCK_STATE.get() == 1; } + /** + * 获取读锁{@link Condition} + * + * @return {@link ReentrantReadWriteLock.ReadLock}的{@link Condition} + * + * @see ReentrantReadWriteLock.ReadLock#newCondition() + * @since 0.1.0 + */ + @NotNull + public + Condition newReadCondition() { return Read_LOCK.newCondition(); } - /** - * 检查写锁是否被占用 - * - * @return 是否被占用 - * - * @since 0.1.0 - */ - public - boolean isWriteLocked() { return LOCK_STATE.get() == 2; } - - /** - * 获取读锁{@link Condition} - * - * @return {@link ReentrantReadWriteLock.ReadLock}的{@link Condition} - * - * @see ReentrantReadWriteLock.ReadLock#newCondition() - * @since 0.1.0 - */ - @NotNull - public - Condition newReadCondition() { return Read_LOCK.newCondition(); } - - /** - * 获取写锁{@link Condition} - * - * @return {@link ReentrantReadWriteLock.WriteLock}的{@link Condition} - * - * @see ReentrantReadWriteLock.WriteLock#newCondition() - * @since 0.1.0 - */ - @NotNull - public - Condition newWriteCondition() { return Write_LOCK.newCondition(); } + /** + * 获取写锁{@link Condition} + * + * @return {@link ReentrantReadWriteLock.WriteLock}的{@link Condition} + * + * @see ReentrantReadWriteLock.WriteLock#newCondition() + * @since 0.1.0 + */ + @NotNull + public + Condition newWriteCondition() { return Write_LOCK.newCondition(); } } \ No newline at end of file diff --git a/src/main/java/fybug/nulll/pdconcurrent/ReLock.java b/src/main/java/fybug/nulll/pdconcurrent/ReLock.java index fbf385b..8defe87 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/ReLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/ReLock.java @@ -17,17 +17,18 @@ import lombok.Getter; *

* 使用并发管理: * {@snippet lang = java: + * public final SyLock lock = new ReLock(); * public static void main(String[] args) { - * var lock = new ReLock(); * lock.read(() -> System.out.println("asdas")); * }} * 不使用: * {@snippet lang = java: * import java.util.concurrent.locks.ReentrantLock; + * + * public final ReentrantLock lock = new ReentrantLock(); * public static void main(String[] args) { - * var lock = new ReentrantLock(); - * lock.lock(); * try { + * lock.lock(); * System.out.println("asdas"); * } finally { * lock.unlock(); @@ -43,140 +44,136 @@ import lombok.Getter; @Getter public class ReLock implements SyLock { - /** 锁 */ - private final ReentrantLock LOCK; - - /** - * 构建并发管理 - *

- * 使用非公平锁 - */ - public - ReLock() { this(false); } - - /** - * 构造并发处理 - * - * @param fair 是否使用公平锁 - */ - public - ReLock(boolean fair) { this(new ReentrantLock(fair)); } + /** 锁 */ + private final ReentrantLock LOCK; - /** - * 构造并发处理 - * - * @param LOCK 使用的锁 - * - * @since 0.1.0 - */ - public - ReLock(@NotNull ReentrantLock LOCK) { this.LOCK = LOCK; } + /** + * 构建并发管理 + *

+ * 使用非公平锁 + */ + public + ReLock() { this(false); } - //---------------------------------------------------------------------------------------------- + /** + * 构造并发处理 + * + * @param fair 是否使用公平锁 + */ + public + ReLock(boolean fair) { this(new ReentrantLock(fair)); } - /** - * {@inheritDoc} - * - * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param catchby {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} - * - * @return {@inheritDoc} - * - * @implNote 使用 {@link ReentrantLock} 实现的并发域,使用了{@link ReentrantLock#lockInterruptibly()}进行可中断的上锁操作 - * @see SyLock#lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - @Override - public - R lock(@NotNull LockType lockType, trySupplier run, @Nullable Function catchby, - @Nullable Function finaby) - { - R o = null; - try { - // 上锁 - if ( lockType != LockType.NOLOCK ) - LOCK.lockInterruptibly(); - // 主要内容 - o = run.get(); - } catch ( Exception e ) { - // 异常处理 - if ( catchby != null ) - o = catchby.apply(e); - } finally { - // 防止错误 - try { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } finally { - // 解锁 - if ( lockType != LockType.NOLOCK && LOCK.isLocked() ) - LOCK.unlock(); - } - } - return o; - } + /** + * 构造并发处理 + * + * @param LOCK 使用的锁 + * + * @since 0.1.0 + */ + public + ReLock(@NotNull ReentrantLock LOCK) { this.LOCK = LOCK; } - /** - * {@inheritDoc} - * - * @param lockType {@inheritDoc} - * @param run {@inheritDoc} - * @param finaby {@inheritDoc} - * @param {@inheritDoc} - * - * @return {@inheritDoc} - * - * @implNote 使用 {@link ReentrantLock} 实现的并发域,使用了{@link ReentrantLock#lockInterruptibly() - * @see SyLock#trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - @Override - public - R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { - R o = null; - try { - // 上锁 - if ( lockType != LockType.NOLOCK ) - LOCK.lockInterruptibly(); - // 主要内容 - o = run.get(); - } finally { - // 防止错误 - try { - // 收尾 - if ( finaby != null ) - o = finaby.apply(o); - } finally { - // 解锁 - if ( lockType != LockType.NOLOCK && LOCK.isLocked() ) - LOCK.unlock(); - } - } - return o; - } + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param catchby {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @implNote 使用 {@link ReentrantLock} 实现的并发域,使用了{@link ReentrantLock#lockInterruptibly()}进行可中断的上锁操作 + * @see SyLock#lock(LockType, trySupplier, Function, Function) + * @since 0.1.0 + */ + @Override + public + R lock(@NotNull LockType lockType, trySupplier run, @Nullable Function catchby, + @Nullable Function finaby) + { + R o = null; + // 防止finally内的回调抛异常 + try { + try { + // 上锁 + if ( lockType != LockType.NOLOCK ) + LOCK.lockInterruptibly(); + // 主要内容 + o = run.get(); + } catch ( Exception e ) { + // 异常处理 + if ( catchby != null ) + o = catchby.apply(e); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } finally { + // 解锁 + if ( lockType != LockType.NOLOCK && LOCK.isLocked() ) + LOCK.unlock(); + } + return o; + } - //---------------------------------------------------------------------------------------------- + /** + * {@inheritDoc} + * + * @param lockType {@inheritDoc} + * @param run {@inheritDoc} + * @param finaby {@inheritDoc} + * @param {@inheritDoc} + * + * @return {@inheritDoc} + * + * @implNote 使用 {@link ReentrantLock} 实现的并发域,使用了{@link ReentrantLock#lockInterruptibly() + * @see SyLock#trylock(LockType, trySupplier, Function) + * @since 0.1.0 + */ + @Override + public + R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception { + R o = null; + // 防止finally内的回调抛异常 + try { + try { + // 上锁 + if ( lockType != LockType.NOLOCK ) + LOCK.lockInterruptibly(); + // 主要内容 + o = run.get(); + } finally { + // 收尾 + if ( finaby != null ) + o = finaby.apply(o); + } + } finally { + // 解锁 + if ( lockType != LockType.NOLOCK && LOCK.isLocked() ) + LOCK.unlock(); + } + return o; + } - /** - * 获取{@link Condition} - * - * @return {@link ReentrantLock}的{@link Condition} - * - * @see ReentrantLock#newCondition() - */ - @NotNull - public - Condition newCondition() { return LOCK.newCondition(); } + /** + * 获取{@link Condition} + * + * @return {@link ReentrantLock}的{@link Condition} + * + * @see ReentrantLock#newCondition() + */ + @NotNull + public + Condition newCondition() { return LOCK.newCondition(); } - /** - * 检查锁是否被占用 - * - * @return 是否被占用 - */ - public - boolean isLocked() { return LOCK.isLocked(); } + /** + * 检查锁是否被占用 + * + * @return 是否被占用 + */ + public + boolean isLocked() { return LOCK.isLocked(); } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/SyLock.java b/src/main/java/fybug/nulll/pdconcurrent/SyLock.java index 4526b1a..1134550 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/SyLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/SyLock.java @@ -18,513 +18,541 @@ import jakarta.validation.constraints.NotNull; * 使用 {@code new**Lock()} 的方法获取不同并发管理的实例
* * @author fybug - * @version 0.1.0 - * @apiNote 并发控制通用接口,规定并实现大部分通用控制功能 + * @version 0.1.1 * @since PDConcurrent 0.0.1 */ public interface SyLock { - /** - * 使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param lockType 锁类型 - * @param run 带返回的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调,传入前两个回调的返回值 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @implSpec 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code catchby}的返回值
- * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,返回应有默认值{@code null}用于应对{@code catchby}和{@code finaby}都为空但是发生了异常的情况 - * @see trySupplier - * @see Function - * @see LockType - * @since 0.1.0 - */ - R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, - @Nullable Function finaby); + /** + * 使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
+ * 所有回调均在并发域内执行 + * + * @param lockType 锁类型 + * @param run 带返回的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + * + * @implSpec 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code catchby}的返回值
+ * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,传递值应默认为{@code null}用于应对{@code catchby}和{@code finaby}都为空但是发生了异常的情况 + * @see trySupplier + * @see Function + * @see LockType + * @since 0.1.0 + */ + R lock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function catchby, + @Nullable Function finaby); - /** - * 使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param lockType 锁类型 - * @param run 执行的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调 - * - * @see tryRunnable - * @see Consumer - * @see Runnable - * @see LockType - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - void lock(@NotNull LockType lockType, @NotNull tryRunnable run, @Nullable Consumer catchby, - @Nullable Runnable finaby) - { - lock(lockType, () -> { - run.run(); - return null; - }, catchby == null ? null : e -> { - catchby.accept(e); - return null; - }, finaby == null ? null : _ -> { - finaby.run(); - return null; - }); - } + /** + * 使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
+ * 所有回调均在并发域内执行 + * + * @param lockType 锁类型 + * @param run 执行的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调 + * + * @see tryRunnable + * @see Consumer + * @see Runnable + * @see LockType + * @see #lock(LockType, trySupplier, Function, Function) + * @since 0.1.0 + */ + default + void lock(@NotNull LockType lockType, @NotNull tryRunnable run, @Nullable Consumer catchby, + @Nullable Runnable finaby) + { + lock(lockType, () -> { + run.run(); + return null; + }, catchby == null ? null : e -> { + catchby.accept(e); + return null; + }, finaby == null ? null : _ -> { + finaby.run(); + return null; + }); + } - //----------------------------------------------- + /** + * 使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,遇到异常不处理返回{@code null} + * + * @param lockType 锁类型 + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常返回{@code null} + * + * @see trySupplier + * @see LockType + * @see #lock(LockType, trySupplier, Function, Function) + * @since 0.1.0 + */ + default + R lock(@NotNull LockType lockType, @NotNull trySupplier run) + { return lock(lockType, run, null, null); } - /** - * 使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,遇到异常不处理返回{@code null} - * - * @param lockType 锁类型 - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常返回{@code null} - * - * @see trySupplier - * @see LockType - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R lock(@NotNull LockType lockType, @NotNull trySupplier run) { return lock(lockType, run, null, null); } + /** + * 使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,遇到异常不处理 + * + * @param lockType 锁类型 + * @param run 执行的回调 + * + * @see tryRunnable + * @see LockType + * @see #lock(LockType, tryRunnable, Consumer, Runnable) + * @since 0.1.0 + */ + default + void lock(@NotNull LockType lockType, @NotNull tryRunnable run) + { lock(lockType, run, null, null); } - /** - * 使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param lockType 锁类型 - * @param run 执行的回调 - * - * @see tryRunnable - * @see LockType - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - void lock(@NotNull LockType lockType, @NotNull tryRunnable run) { - lock(lockType, () -> { - run.run(); - return null; - }, null, null); - } + /** + * 尝试使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
+ * 所有回调均在并发域内执行 + * + * @param lockType 锁类型 + * @param run 带返回的回调 + * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @implSpec 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code null}
+ * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,发生异常会执行{@code finaby}但是不会返回内容 + * @see trySupplier + * @see Function + * @see LockType + * @since 0.1.0 + */ + R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception; - //----------------------------------------------- + /** + * 尝试使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
+ * 所有回调均在并发域内执行 + * + * @param lockType 锁类型 + * @param run 执行的回调 + * @param finaby 进入finally块后的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see tryRunnable + * @see Runnable + * @see LockType + * @see #trylock(LockType, trySupplier, Function) + * @since 0.1.0 + */ + default + void trylock(@NotNull LockType lockType, @NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception { + trylock(lockType, () -> { + run.run(); + return null; + }, finaby == null ? null : _ -> { + finaby.run(); + return null; + }); + } - /** - * 尝试使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
- * 所有回调均在并发域内执行 - * - * @param lockType 锁类型 - * @param run 带返回的回调 - * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @implSpec 如果有传入 {@code finaby} 回调则返回值由{@code finaby}主导,传入{@code finaby}的值根据是否发生异常传入{@code run}的返回值或{@code null}
- * 任意一个回调为空时直接穿透,使用上一个正确执行的值进行传递或者返回,发生异常会执行{@code finaby}但是不会返回内容 - * @see trySupplier - * @see Function - * @see LockType - * @since 0.1.0 - */ - R trylock(@NotNull LockType lockType, @NotNull trySupplier run, @Nullable Function finaby) throws Exception; + /** + * 尝试使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,遇到异常会抛出 + * + * @param lockType 锁类型 + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see trySupplier + * @see LockType + * @see #trylock(LockType, trySupplier, Function) + * @since 0.1.0 + */ + default + R trylock(@NotNull LockType lockType, @NotNull trySupplier run) throws Exception + { return trylock(lockType, run, null); } - /** - * 尝试使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
- * 所有回调均在并发域内执行 - * - * @param lockType 锁类型 - * @param run 执行的回调 - * @param finaby 进入finally块后的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see tryRunnable - * @see Runnable - * @see LockType - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - void trylock(@NotNull LockType lockType, @NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception { - trylock(lockType, () -> { - run.run(); - return null; - }, finaby == null ? null : _ -> { - finaby.run(); - return null; - }); - } + /** + * 尝试使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,遇到异常会抛出 + * + * @param lockType 锁类型 + * @param run 执行的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see tryRunnable + * @see LockType + * @see #trylock(LockType, tryRunnable, Runnable) + * @since 0.1.0 + */ + default + void trylock(@NotNull LockType lockType, @NotNull tryRunnable run) throws Exception + { trylock(lockType, run, null); } - //----------------------------------------------- + /** + * 使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带try-catch-finally块,遇到异常不处理 + * + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + * + * @see trySupplier + * @see LockType#READ + * @see #lock(LockType, trySupplier, Function, Function) + * @since 0.1.0 + */ + default + R read(@NotNull trySupplier run) + { return lock(LockType.READ, run, null, null); } - /** - * 尝试使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,遇到异常会抛出 - * - * @param lockType 锁类型 - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - R trylock(@NotNull LockType lockType, @NotNull trySupplier run) throws Exception - { return trylock(lockType, run, null); } + /** + * 使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带try-catch-finally块,遇到异常不处理 + * + * @param run 执行的回调 + * + * @see tryRunnable + * @see LockType#READ + * @see #lock(LockType, tryRunnable, Consumer, Runnable) + * @since 0.1.0 + */ + default + void read(@NotNull tryRunnable run) + { lock(LockType.READ, run, null, null); } - /** - * 尝试使用锁执行指定回调 - *

- * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,遇到异常会抛出 - * - * @param lockType 锁类型 - * @param run 执行的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see tryRunnable - * @see LockType - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - void trylock(@NotNull LockType lockType, @NotNull tryRunnable run) throws Exception { - trylock(lockType, () -> { - run.run(); - return null; - }, null); - } + /** + * 使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-catch-finally块,遇到异常不处理 + * + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + * + * @see trySupplier + * @see LockType#WRITE + * @see #lock(LockType, trySupplier, Function, Function) + * @since 0.1.0 + */ + default + R write(@NotNull trySupplier run) + { return lock(LockType.WRITE, run, null, null); } - /*--------------------------------------------------------------------------------------------*/ + /** + * 使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-catch-finally块,遇到异常不处理 + * + * @param run 执行的回调 + * + * @see tryRunnable + * @see LockType#WRITE + * @see #lock(LockType, tryRunnable, Consumer, Runnable) + * @since 0.1.0 + */ + default + void write(@NotNull tryRunnable run) + { lock(LockType.WRITE, run, null, null); } - /** - * 使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @see trySupplier - * @see LockType#READ - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R read(@NotNull trySupplier run) { return lock(LockType.READ, run, null, null); } + /** + * 使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
+ * 所有回调均在并发域内执行 + * + * @param run 带返回的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + * + * @see trySupplier + * @see Function + * @see LockType#READ + * @see #lock(LockType, trySupplier, Function, Function) + * @since 0.1.0 + */ + default + R read(@NotNull trySupplier run, @Nullable Function catchby, @Nullable Function finaby) + { return lock(LockType.READ, run, catchby, finaby); } - /** - * 使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param run 执行的回调 - * - * @see tryRunnable - * @see LockType#READ - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - void read(@NotNull tryRunnable run) { - lock(LockType.READ, () -> { - run.run(); - return null; - }, null, null); - } + /** + * 使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
+ * 所有回调均在并发域内执行 + * + * @param run 执行的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调 + * + * @see tryRunnable + * @see Consumer + * @see Runnable + * @see LockType#READ + * @see #lock(LockType, tryRunnable, Consumer, Runnable) + * @since 0.1.0 + */ + default + void read(@NotNull tryRunnable run, @Nullable Consumer catchby, @Nullable Runnable finaby) + { lock(LockType.READ, run, catchby, finaby); } - /** - * 使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @see trySupplier - * @see LockType#WRITE - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R write(@NotNull trySupplier run) { return lock(LockType.WRITE, run, null, null); } + /** + * 使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
+ * 所有回调均在并发域内执行 + * + * @param run 带返回的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调,传入前两个回调的返回值 + * @param 要返回的数据类型 + * + * @return 回调返回的内容 + * + * @see trySupplier + * @see Function + * @see LockType#WRITE + * @see #lock(LockType, trySupplier, Function, Function) + * @since 0.1.0 + */ + default + R write(@NotNull trySupplier run, @Nullable Function catchby, @Nullable Function finaby) + { return lock(LockType.WRITE, run, catchby, finaby); } - /** - * 使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-catch-finally块,遇到异常不处理 - * - * @param run 执行的回调 - * - * @see tryRunnable - * @see LockType#WRITE - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - void write(@NotNull tryRunnable run) { - lock(LockType.WRITE, () -> { - run.run(); - return null; - }, null, null); - } + /** + * 使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
+ * 所有回调均在并发域内执行 + * + * @param run 执行的回调 + * @param catchby 进入catch块后的回调,传入当前异常 + * @param finaby 进入finally块后的回调 + * + * @see tryRunnable + * @see Consumer + * @see Runnable + * @see LockType#WRITE + * @see #lock(LockType, tryRunnable, Consumer, Runnable) + * @since 0.1.0 + */ + default + void write(@NotNull tryRunnable run, @Nullable Consumer catchby, @Nullable Runnable finaby) + { lock(LockType.WRITE, run, catchby, finaby); } - //----------------------------------------------- + /** + * 尝试使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带try-finally块,遇到异常会抛出 + * + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see trySupplier + * @see LockType#READ + * @see #trylock(LockType, trySupplier, Function) + * @since 0.1.0 + */ + default + R tryread(@NotNull trySupplier run) throws Exception + { return trylock(LockType.READ, run, null); } - /** - * 使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param run 带返回的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调,传入前两个回调的返回值 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @see trySupplier - * @see Function - * @see LockType#READ - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R read(@NotNull trySupplier run, @Nullable Function catchby, @Nullable Function finaby) - { return lock(LockType.READ, run, catchby, finaby); } + /** + * 尝试使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带try-finally块,遇到异常会抛出 + * + * @param run 执行的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see tryRunnable + * @see LockType#READ + * @see #trylock(LockType, tryRunnable, Runnable) + * @since 0.1.0 + */ + default + void tryread(@NotNull tryRunnable run) throws Exception + { trylock(LockType.READ, run, null); } - /** - * 使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param run 执行的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调 - * - * @see tryRunnable - * @see Consumer - * @see Runnable - * @see LockType#READ - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - void read(@NotNull tryRunnable run, @Nullable Consumer catchby, @Nullable Runnable finaby) { - lock(LockType.READ, () -> { - run.run(); - return null; - }, catchby == null ? null : e -> { - catchby.accept(e); - return null; - }, finaby == null ? null : _ -> { - finaby.run(); - return null; - }); - } + /** + * 尝试使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-finally块,遇到异常会抛出 + * + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see trySupplier + * @see LockType#WRITE + * @see #trylock(LockType, trySupplier, Function) + * @since 0.1.0 + */ + default + R trywrite(@NotNull trySupplier run) throws Exception + { return trylock(LockType.WRITE, run, null); } - /** - * 使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param run 带返回的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调,传入前两个回调的返回值 - * @param 要返回的数据类型 - * - * @return 回调返回的内容 - * - * @see trySupplier - * @see Function - * @see LockType#WRITE - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - R write(@NotNull trySupplier run, @Nullable Function catchby, @Nullable Function finaby) - { return lock(LockType.WRITE, run, catchby, finaby); } + /** + * 尝试使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-finally块,遇到异常会抛出 + * + * @param run 执行的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see tryRunnable + * @see LockType#WRITE + * @see #trylock(LockType, tryRunnable, Runnable) + * @since 0.1.0 + */ + default + void trywrite(@NotNull tryRunnable run) throws Exception + { trylock(LockType.WRITE, run, null); } - /** - * 使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-catch-finally块,通过三个回调参数插入不同的块中执行
- * 所有回调均在并发域内执行 - * - * @param run 执行的回调 - * @param catchby 进入catch块后的回调,传入当前异常 - * @param finaby 进入finally块后的回调 - * - * @see tryRunnable - * @see Consumer - * @see Runnable - * @see LockType#WRITE - * @see #lock(LockType, trySupplier, Function, Function) - * @since 0.1.0 - */ - default - void write(@NotNull tryRunnable run, @Nullable Consumer catchby, @Nullable Runnable finaby) { - lock(LockType.WRITE, () -> { - run.run(); - return null; - }, catchby == null ? null : e -> { - catchby.accept(e); - return null; - }, finaby == null ? null : _ -> { - finaby.run(); - return null; - }); - } + /** + * 尝试使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
+ * 所有回调均在并发域内执行 + * + * @param run 带返回的回调 + * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see trySupplier + * @see LockType#READ + * @see #trylock(LockType, trySupplier, Function) + * @since 0.1.0 + */ + default + R tryread(@NotNull trySupplier run, @Nullable Function finaby) throws Exception + { return trylock(LockType.READ, run, finaby); } - //----------------------------------------------- + /** + * 尝试使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
+ * 所有回调均在并发域内执行 + * + * @param run 执行的回调 + * @param finaby 进入finally块后的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see trySupplier + * @see LockType#READ + * @see #trylock(LockType, tryRunnable, Runnable) + * @since 0.1.1 + */ + default + void tryread(@NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception + { trylock(LockType.READ, run, finaby); } - /** - * 尝试使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-finally块,遇到异常会抛出 - * - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType#READ - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - R tryread(@NotNull trySupplier run) throws Exception { return trylock(LockType.READ, run, null); } + /** + * 尝试使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
+ * 所有回调均在并发域内执行 + * + * @param run 带返回的回调 + * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see trySupplier + * @see LockType#WRITE + * @see #trylock(LockType, trySupplier, Function) + * @since 0.1.1 + */ + default + R trywrite(@NotNull trySupplier run, @Nullable Function finaby) throws Exception + { return trylock(LockType.WRITE, run, finaby); } - /** - * 尝试使用读锁执行指定回调 - *

- * 调用读锁执行,运行时自带try-finally块,遇到异常会抛出 - * - * @param run 执行的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see tryRunnable - * @see LockType#READ - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - void tryread(@NotNull tryRunnable run) throws Exception { - trylock(LockType.READ, () -> { - run.run(); - return null; - }, null); - } + /** + * 尝试使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
+ * 所有回调均在并发域内执行 + * + * @param run 执行的回调 + * @param finaby 进入finally块后的回调 + * + * @throws Exception 异常类型根据实际运行时回调抛出决定 + * @see trySupplier + * @see LockType#WRITE + * @see #trylock(LockType, tryRunnable, Runnable) + * @since 0.1.1 + */ + default + void trywrite(@NotNull tryRunnable run, @Nullable Runnable finaby) throws Exception + { trylock(LockType.WRITE, run, finaby); } - /** - * 尝试使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-finally块,遇到异常会抛出 - * - * @param run 带返回的回调 - * @param 要返回的数据类型 - * - * @return 回调返回的内容,遇到异常不返回 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see trySupplier - * @see LockType#WRITE - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - R trywrite(@NotNull trySupplier run) throws Exception { return trylock(LockType.WRITE, run, null); } + /** + * 获取传统并发实现 + * + * @return 获取的并发控制对象 + * + * @see ObjLock + */ + @NotNull + static + ObjLock newObjLock() { return new ObjLock(); } - /** - * 尝试使用写锁执行指定回调 - *

- * 调用写锁执行,运行时自带try-finally块,遇到异常会抛出 - * - * @param run 执行的回调 - * - * @throws Exception 异常类型根据实际运行时回调抛出决定 - * @see tryRunnable - * @see LockType#WRITE - * @see #trylock(LockType, trySupplier, Function) - * @since 0.1.0 - */ - default - void trywrite(@NotNull tryRunnable run) throws Exception { - trylock(LockType.WRITE, () -> { - run.run(); - return null; - }, null); - } + /** + * 获取可重入锁实现 + * + * @return 获取的并发控制对象 + * + * @see ReLock + */ + @NotNull + static + ReLock newReLock() { return new ReLock(); } - /*--------------------------------------------------------------------------------------------*/ - - /** - * 获取传统并发实现 - * - * @return 获取的并发控制对象 - * - * @see ObjLock - */ - @NotNull - static - ObjLock newObjLock() { return new ObjLock(); } - - /** - * 获取可重入锁实现 - * - * @return 获取的并发控制对象 - * - * @see ReLock - */ - @NotNull - static - ReLock newReLock() { return new ReLock(); } - - /** - * 获取读写锁实现 - * - * @return 获取的并发控制对象 - * - * @see RWLock - */ - @NotNull - static - RWLock newRWLock() { return new RWLock(); } + /** + * 获取读写锁实现 + * + * @return 获取的并发控制对象 + * + * @see RWLock + */ + @NotNull + static + RWLock newRWLock() { return new RWLock(); } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/e/LockType.java b/src/main/java/fybug/nulll/pdconcurrent/e/LockType.java index 0d722ea..0562106 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/e/LockType.java +++ b/src/main/java/fybug/nulll/pdconcurrent/e/LockType.java @@ -9,10 +9,10 @@ package fybug.nulll.pdconcurrent.e; */ public enum LockType { - /** 读锁 */ - READ, - /** 写锁 */ - WRITE, - /** 不上锁 */ - NOLOCK + /** 读锁 */ + READ, + /** 写锁 */ + WRITE, + /** 不上锁 */ + NOLOCK } diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java b/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java index c02de60..b1a3114 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java @@ -14,35 +14,35 @@ import jakarta.validation.constraints.NotNull; */ public interface tryConsumer { - /** @see Consumer#accept(Object) */ - void accept(T t) throws Exception; + /** @see Consumer#accept(Object) */ + void accept(T t) throws Exception; - /** @since 0.0.2 */ - @NotNull - default - tryConsumer andThen(@Nullable tryRunnable after) { - if ( after != null ) { - return t -> { - accept(t); - after.run(); - }; - } - return this; - } + /** @since 0.0.2 */ + @NotNull + default + tryConsumer andThen(@Nullable tryRunnable after) { + if ( after != null ) { + return t -> { + accept(t); + after.run(); + }; + } + return this; + } - /** @since 0.0.2 */ - @NotNull - default - tryFunction andThen(@Nullable trySupplier after) { - if ( after != null ) { - return t -> { - accept(t); - return after.get(); - }; - } - return t -> { - accept(t); - return null; - }; - } + /** @since 0.0.2 */ + @NotNull + default + tryFunction andThen(@Nullable trySupplier after) { + if ( after != null ) { + return t -> { + accept(t); + return after.get(); + }; + } + return t -> { + accept(t); + return null; + }; + } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java b/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java index aeeed13..d3fa122 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java @@ -15,24 +15,24 @@ import jakarta.validation.constraints.NotNull; */ public interface tryFunction { - /** @see Function#apply(Object) */ - R apply(T t) throws Exception; + /** @see Function#apply(Object) */ + R apply(T t) throws Exception; - /** @since 0.0.2 */ - @NotNull - default - tryConsumer andThen(@Nullable tryConsumer after) { - if ( after != null ) - return t -> after.accept(apply(t)); - return this::apply; - } + /** @since 0.0.2 */ + @NotNull + default + tryConsumer andThen(@Nullable tryConsumer after) { + if ( after != null ) + return t -> after.accept(apply(t)); + return this::apply; + } - /** @since 0.0.2 */ - @NotNull - default - tryFunction andThen(@Nullable tryFunction after) { - if ( after != null ) - return t -> after.apply(apply(t)); - return (tryFunction) this; - } + /** @since 0.0.2 */ + @NotNull + default + tryFunction andThen(@Nullable tryFunction after) { + if ( after != null ) + return t -> after.apply(apply(t)); + return (tryFunction) this; + } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java b/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java index 970eeac..99be436 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java @@ -11,64 +11,64 @@ import jakarta.validation.constraints.NotNull; @FunctionalInterface public interface tryRunnable { - /** @see Runnable#run() */ - void run() throws Exception; + /** @see Runnable#run() */ + void run() throws Exception; - /** @since 0.0.2 */ - @NotNull - default - tryRunnable andThen(@Nullable tryRunnable after) { - if ( after != null ) { - return () -> { - run(); - after.run(); - }; - } - return this; - } + /** @since 0.0.2 */ + @NotNull + default + tryRunnable andThen(@Nullable tryRunnable after) { + if ( after != null ) { + return () -> { + run(); + after.run(); + }; + } + return this; + } - /** @since 0.0.2 */ - @NotNull - default - trySupplier andThen(@Nullable trySupplier after) { - if ( after != null ) { - return () -> { - run(); - return after.get(); - }; - } - return () -> { - run(); - return null; - }; - } + /** @since 0.0.2 */ + @NotNull + default + trySupplier andThen(@Nullable trySupplier after) { + if ( after != null ) { + return () -> { + run(); + return after.get(); + }; + } + return () -> { + run(); + return null; + }; + } - /** @since 0.0.2 */ - @NotNull - default - tryRunnable andThen(@Nullable tryConsumer after) { - if ( after != null ) { - return () -> { - run(); - after.accept(null); - }; - } - return this; - } + /** @since 0.0.2 */ + @NotNull + default + tryRunnable andThen(@Nullable tryConsumer after) { + if ( after != null ) { + return () -> { + run(); + after.accept(null); + }; + } + return this; + } - /** @since 0.0.2 */ - @NotNull - default - trySupplier andThen(@Nullable tryFunction after) { - if ( after != null ) { - return () -> { - run(); - return after.apply(null); - }; - } - return () -> { - run(); - return null; - }; - } + /** @since 0.0.2 */ + @NotNull + default + trySupplier andThen(@Nullable tryFunction after) { + if ( after != null ) { + return () -> { + run(); + return after.apply(null); + }; + } + return () -> { + run(); + return null; + }; + } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java b/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java index d1b8ebf..5acbc79 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java @@ -15,24 +15,24 @@ import jakarta.validation.constraints.NotNull; @FunctionalInterface public interface trySupplier { - /** @see Supplier#get() */ - R get() throws Exception; + /** @see Supplier#get() */ + R get() throws Exception; - /** @since 0.0.2 */ - @NotNull - default - tryRunnable andThen(@Nullable tryConsumer after) { - if ( after != null ) - return () -> after.accept(get()); - return this::get; - } + /** @since 0.0.2 */ + @NotNull + default + tryRunnable andThen(@Nullable tryConsumer after) { + if ( after != null ) + return () -> after.accept(get()); + return this::get; + } - /** @since 0.0.2 */ - @NotNull - default - trySupplier andThen(@Nullable tryFunction after) { - if ( after != null ) - return () -> after.apply(get()); - return (trySupplier) this; - } + /** @since 0.0.2 */ + @NotNull + default + trySupplier andThen(@Nullable tryFunction after) { + if ( after != null ) + return () -> after.apply(get()); + return (trySupplier) this; + } } diff --git a/src/main/java/fybug/nulll/pdconcurrent/package-info.java b/src/main/java/fybug/nulll/pdconcurrent/package-info.java index 640060a..b3e8496 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/package-info.java +++ b/src/main/java/fybug/nulll/pdconcurrent/package-info.java @@ -5,7 +5,7 @@ * 附带{@code try***}的功能接口包{@link fybug.nulll.pdconcurrent.fun},在java原有的功能接口的基础上允许抛出异常 * * @author fybug - * @version 0.1.0 + * @version 0.1.1 * @since JDK 23+ */ package fybug.nulll.pdconcurrent; \ No newline at end of file diff --git a/src/test/java/a.java b/src/test/java/a.java deleted file mode 100644 index d82921a..0000000 --- a/src/test/java/a.java +++ /dev/null @@ -1,29 +0,0 @@ -public -class a { - public static - void main(String[] args) { - try { - System.out.println(a()); - } catch ( Exception e ) { - System.out.println("11111"); - } - } - - private static - String a() throws Exception { - String a; - try { - a = "2"; - b(); - } finally { - a = "3"; - System.out.println("11111"); - } - return a; - } - - private static - void b() throws Exception { - throw new Exception(); - } -} -- Gitee