diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..8af972cded0d3e3ccb3c6e801150168bcc93150a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +/gradlew text eol=lf +*.bat text eol=crlf +*.jar binary diff --git a/.gitignore b/.gitignore index 3ee9f36f53f97ee347cd95332ba4e5578c13215c..c2065bc26202b2d072aca3efc3d1c2efad3afcbf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,37 @@ -pdfunctionlibrary.properties -pdfunctionlibrary.xml -# Ignore Gradle GUI config -gradle-app.setting +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ -# Cache of project -.gradletasknamecache +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ -.gradle/ -.idea/ -build/ -gradlew.bat -gradlew +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ -# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 -# gradle/wrapper/gradle-wrapper.properties +### VS Code ### +.vscode/ diff --git a/README.md b/README.md index 8660d33377a2d60d09b3367a7d60212012c6c984..d71eb39f1ee3f312e5b4ab5a7aba2077cde934e7 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ # PDConcurrent ![java library](https://img.shields.io/badge/type-Libary-gr.svg "type") -![JDK 14](https://img.shields.io/badge/JDK-14-green.svg "SDK") -![Gradle 6.5](https://img.shields.io/badge/Gradle-6.5-04303b.svg "tool") +![JDK 23](https://img.shields.io/badge/JDK-23-green.svg "SDK") +![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) -- @@ -28,16 +28,13 @@ ### \> > 基础使用示例 ```java -// 尝试申请读锁 -SyLock.newObjLock().read(() -> { +public static void main(String[] args) { + var lock = SyLock.newObjLock(); + lock.read(() -> { // 并发域代码内容 [return null;]? // 可选择是否返回 -}); - -// 尝试申请写锁 -SyLock.newObjLock().write(() -> { - [return null;]? -}); + }); +} ``` 以上即为核心用法,将需要并发处理的代码通过一个 `Runnable` 接口包起来。启用并发管理以及停止并发管理部分的的代码由本工具封装,直接通过上述代码的方式传入需要运行的内容即可 @@ -50,48 +47,58 @@ SyLock.newObjLock().write(() -> { ### \> > synchronized 锁 ```java -// 使用 -SyLock.newObjLock().read(() -> { +public static void main(String[] args) { + // 使用 + var lock = SyLock.newObjLock(); + lock.read(() -> { // 并发域代码内容 -}); + }); -// 不使用 -synchronized ( new Object() ){ + // 不使用 + synchronized ( new Object() ){ // 并发域代码内容 + } } + ``` ### \> > ReentrantLock 锁 ```java -// 使用 -SyLock.newReLock().read(() -> { +public static void main(String[] args) { + // 使用 + var lock = SyLock.newReLock(); + lock.read(() -> { // 并发域代码内容 -}); + }); -// 不使用 -ReentrantLock lock = new ReentrantLock(); -try { + // 不使用 + ReentrantLock lock = new ReentrantLock(); + try { lock.lock(); // 并发域代码内容 -} finally { + } finally { lock.unlock(); + } } ``` ### \> > ReadWriteLock 锁 ```java -// 使用 -SyLock.newRWLock().read(() -> { +public static void main(String[] args) { + // 使用 + var lock = SyLock.newRWLock(); + lock.read(() -> { // 并发域代码内容 -}); + }); -// 不使用 -ReadWriteLock lock = new ReentrantReadWriteLock(); -try { + // 不使用 + ReadWriteLock lock = new ReentrantReadWriteLock(); + try { lock.readLock().lock(); // 并发域代码内容 -} finally { + } finally { lock.readLock().unlock(); + } } ``` @@ -100,8 +107,6 @@ try { > PDConcurrent.jar 为不包含源码的包 > -> PDConcurrent_all.jar 为包含了源码的包 -> > PDConcurrent_sources.jar 为仅包含源码的包 **发行版中可以看到全部版本
项目下的 jar 文件夹是当前最新的每夜版** diff --git a/build.gradle b/build.gradle index c0a688bde4e8a9bcf1a5ba7893e9cd6a64f72748..7fad4d0c2c7dd5b1d2699d64abd737d83a456e86 100644 --- a/build.gradle +++ b/build.gradle @@ -1,105 +1,125 @@ plugins { - id 'java' - id 'idea' + id 'java' + id 'idea' } -tasks.withType(JavaCompile) { - options.encoding = "UTF-8" +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" } group 'fybug.nulll' -version = '0.0.2' -sourceCompatibility = '14' -targetCompatibility = '14' +version = '0.1.0' -configurations { - developmentOnly - runtimeClasspath { - extendsFrom developmentOnly - } - compileOnly { - extendsFrom annotationProcessor - } +java { + toolchain { + languageVersion = JavaLanguageVersion.of(23) + } } repositories { - mavenLocal() - mavenCentral() - maven { url 'https://repo.spring.io/milestone' } - maven { url 'https://repo.spring.io/snapshot' } - 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/apache-snapshots" } - maven { url "http://repo.spring.io/milestone" } + 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']) - compileOnly "org.jetbrains:annotations:17.0.0" - compileOnly "org.projectlombok:lombok:1.18.10" - annotationProcessor "org.projectlombok:lombok:1.18.10" + implementation fileTree(dir: 'lib', includes: ['*.jar']) - testCompile "junit:junit:4.12" - testCompileOnly "org.jetbrains:annotations:17.0.0" - testCompileOnly "org.projectlombok:lombok:1.18.10" + compileOnly "jakarta.validation:jakarta.validation-api:+" + compileOnly "jakarta.annotation:jakarta.annotation-api:+" + compileOnly 'org.projectlombok:lombok:+' + annotationProcessor 'org.projectlombok:lombok:+' + + // testImplementation "junit:junit" + testCompileOnly "jakarta.validation:jakarta.validation-api:+" + testCompileOnly "jakarta.annotation:jakarta.annotation-api:+" + testCompileOnly "org.projectlombok:lombok:+" + testAnnotationProcessor "org.projectlombok:lombok:+" +} + +test { + useJUnitPlatform() } -task PDConcurrent(type: Jar) { - destinationDirectory = file('jar') - manifest { - attributes( - 'Manifest-Version': '1.0', - 'Built-By': 'fybug/风雨bu改', - 'Created-By': 'IntelliJ IDEA' - ) - } - archiveFileName = 'PDConcurrent.jar' - // 打包编译输出 - from sourceSets.main.output +task PDConcurrent_bin(type: Jar) { + 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') + } + archiveFileName = 'PDConcurrent_bin.jar' + // 打包编译输出 + from sourceSets.main.output } task PDConcurrent_all(type: Jar) { - destinationDirectory = file('jar') - manifest { - attributes( - 'Manifest-Version': '1.0', - 'Built-By': 'fybug/风雨bu改', - 'Created-By': 'IntelliJ IDEA' - ) - } - archiveFileName = 'PDConcurrent_all.jar' - // 打包编译输出 - from sourceSets.main.output - // 打包源码 - from sourceSets.main.allSource - from { - // implementation 相关的引入解压并打包入新的jar中 - configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } - } + 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') + } + archiveFileName = 'PDConcurrent_all.jar' + // 打包编译输出 + from sourceSets.main.output + // 打包源码 + from sourceSets.main.allSource + from { + // implementation 相关的引入解压并打包入新的jar中 + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } } task PDConcurrent_sources(type: Jar) { - destinationDirectory = file('jar') - manifest { - attributes( - 'Manifest-Version': '1.0', - 'Built-By': 'fybug/风雨bu改', - 'Created-By': 'IntelliJ IDEA' - ) - } - archiveFileName = 'PDConcurrent_sources.jar' - // 打包源码 - from sourceSets.main.allSource + 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') + } + archiveFileName = 'PDConcurrent_sources.jar' + // 打包源码 + from sourceSets.main.allSource } task release { - dependsOn clean - dependsOn PDConcurrent_all - dependsOn PDConcurrent - dependsOn PDConcurrent_sources + dependsOn clean + dependsOn PDConcurrent_bin + dependsOn PDConcurrent_sources } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..a4b76b9530d66f5e68d973ea569d8e19de379189 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 622ab64a3cb60378cd29384961554c0b032c9368..df97d72b8b91fa0e088ae27b1c84a6063481fe22 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000000000000000000000000000000000000..f5feea6d6b116baaca5a2642d4d9fa1f47d574a7 --- /dev/null +++ b/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000000000000000000000000000000000..27bf976f8e2ed20d0cc85746c8eabfc40d1765bd --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain DocumentType copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/jar/PDConcurrent.jar b/jar/PDConcurrent.jar deleted file mode 100644 index 8ec6fad1d7a5d6088a2f411adaa0c4f4b28a6827..0000000000000000000000000000000000000000 Binary files a/jar/PDConcurrent.jar and /dev/null differ diff --git a/jar/PDConcurrent_all.jar b/jar/PDConcurrent_all.jar deleted file mode 100644 index ed9e7863610ec3b9360c8e6126ade0885b35b8db..0000000000000000000000000000000000000000 Binary files a/jar/PDConcurrent_all.jar and /dev/null differ diff --git a/jar/PDConcurrent_bin.jar b/jar/PDConcurrent_bin.jar new file mode 100644 index 0000000000000000000000000000000000000000..27dd86ee8081117386b9cd6d9a9f3c06e787a8ca Binary files /dev/null and b/jar/PDConcurrent_bin.jar differ diff --git a/jar/PDConcurrent_sources.jar b/jar/PDConcurrent_sources.jar index bd9b5d8344b9bb4cf57a91fae0a48d0e4344be80..ea47ab642fe7fe7c73d815ec53d8dfee75682fae 100644 Binary files a/jar/PDConcurrent_sources.jar and b/jar/PDConcurrent_sources.jar differ diff --git a/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java b/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java index 4d5070d17f35a970fbb808ea66cc897521d21f82..d36d99e2036d341ddf59b6f388ebc4dda0b00e7e 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/ObjLock.java @@ -1,81 +1,158 @@ package fybug.nulll.pdconcurrent; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Supplier; +import java.util.function.Function; +import fybug.nulll.pdconcurrent.e.LockType; import fybug.nulll.pdconcurrent.fun.trySupplier; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; import lombok.Getter; /** *

使用传统并发管理的实现.

- *
使用并发管理:
- *     public static
- *     void main(String[] args) {
- *         var lock = new ObjLock();
- *         lock.read(() -> System.out.println("asd"));
- *     }
- *
不使用:
- *     public static
- *     void main(String[] args) {
- *         synchronized ( new Object() ){
- *             System.out.println("asd");
- *         }
- *     }
+ * 使用{@code synchronized( Object )}实现并发域,读写锁均为同一个实现 + *

+ * 使用并发管理: + * {@snippet lang = java: + * public static void main(String[] args) { + * var lock = new ObjLock(); + * lock.read(() -> System.out.println("asd")); + * }} + * 不使用: + * {@snippet lang = java: + * public static void main(String[] args) { + * Object lock = new Object(); + * synchronized ( lock ){ + * System.out.println("asd"); + * } + * }} * * @author fybug - * @version 0.0.1 + * @version 0.1.0 + * @see SyLock * @since PDConcurrent 0.0.1 */ +@Getter public class ObjLock implements SyLock { + /** 作为锁的对象 */ + private final Object LOCK; - /** 锁定的对象 */ - @Getter final private Object LOCK; - - public - ObjLock() {this(new Object());} - - /** 生成并发管理,并指定使用的并发对象锁 */ - public - ObjLock(@NotNull Object lock) {LOCK = lock;} - - //---------------------------------------------------------------------------------------------- - - @Override - public - T read(@NotNull Supplier run) { return run(run); } - - @Override - public - T write(@NotNull Supplier run) { return run(run); } - - // 读写一致 - private - T run(Supplier run) { - synchronized ( LOCK ){ - return run.get(); - } - } + /** + * 构建并发管理 + *

+ * 使用一个新的{@link Object} + */ + public + ObjLock() { this(new Object()); } - //---------------------------------------------------------------------------------------------- + /** + * 构建并发管理 + * + * @param lock 用作锁的对象 + * + * @since 0.1.0 + */ + public + ObjLock(@NotNull Object lock) { LOCK = lock; } - @Override - public - T tryread(@NotNull Class ecla, @NotNull trySupplier run) - throws E - { return tryrun(ecla, run); } + //---------------------------------------------------------------------------------------------- - @Override - public - T trywrite(@NotNull Class ecla, @NotNull trySupplier run) - throws E - { return tryrun(ecla, run); } + /** + * {@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; + } - // 读写一致 - private - T tryrun(Class ecla, trySupplier run) throws E { - synchronized ( LOCK ){ - return run.get(); - } - } + /** + * {@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 bff3d7722972f2e15f29605c001f387aa76c45ce..bbd33e30dd6fbaedd6122c0327b799d651241729 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/RWLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/RWLock.java @@ -1,123 +1,316 @@ package fybug.nulll.pdconcurrent; -import org.jetbrains.annotations.NotNull; - import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Supplier; +import java.util.function.Function; +import fybug.nulll.pdconcurrent.e.LockType; import fybug.nulll.pdconcurrent.fun.trySupplier; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; import lombok.Getter; /** - * 使用读写锁 {@link ReentrantReadWriteLock} 实现的并发管理 - *

使用并发管理:
- *     public static
- *     void main(String[] args) {
- *         var lock = new RWLock();
- *         lock.read(() -> System.out.println("adsa"));
- *         lock.write(() -> System.out.println("adsa"));
- *     }
- *
不使用:
- *     public static
- *     void main(String[] args) {
- *         var lock = new ReentrantReadWriteLock();
- *         lock.readLock().lock();
- *         try {
- *             System.out.println("adsa");
- *         } finally {
- *             lock.readLock().unlock();
- *         }
- *         lock.writeLock().lock();
- *         try {
- *             System.out.println("adsa");
- *         } finally {
- *             lock.writeLock().unlock();
- *         }
- *     }
+ *

使用{@link ReentrantReadWriteLock}实现的并发管理.

+ * 使用{@link ReentrantReadWriteLock}实现并发域,读写锁均为标准实现,支持通过{@link #toread()}进行锁降级
+ * 使用了可中断的上锁操作{@link ReentrantReadWriteLock.ReadLock#lockInterruptibly()}和{@link ReentrantReadWriteLock.WriteLock#lockInterruptibly()}
+ * 支持使用{@link #newReadCondition()}{@link #newWriteCondition()}获取{@link Condition},通过{@link #isLocked()}{@link #isWriteLocked()}{@link #isReadLocked()}检查是否被占用
+ *

+ * 使用并发管理: + * {@snippet lang = java: + * public static void main(String[] args) { + * var lock = new RWLock(); + * // 使用读锁 + * lock.read(() -> System.out.println("adsa")); + * // 使用写锁 + * lock.write(() -> System.out.println("adsa")); + * }} + * 不使用: + * {@snippet lang = java: + * import java.util.concurrent.locks.ReentrantReadWriteLock; + * public static void main(String[] args) { + * var lock = new ReentrantReadWriteLock(); + * // 使用读锁 + * try { + * lock.readLock().lock(); + * System.out.println("adsa"); + * } finally { + * lock.readLock().unlock(); + * } + * // 使用写锁 + * try { + * lock.writeLock().lock(); + * System.out.println("adsa"); + * } finally { + * lock.writeLock().unlock(); + * } + * }} * * @author fybug - * @version 0.0.1 + * @version 0.1.0 + * @see SyLock + * @see LockType + * @see ReentrantReadWriteLock + * @see ReentrantReadWriteLock.ReadLock + * @see ReentrantReadWriteLock.WriteLock * @since PDConcurrent 0.0.1 */ +@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<>(); + + /** + * 构建并发管理 + *

+ * 使用非公平锁 + */ + public + RWLock() { this(false); } + + /** + * 构造并发处理 + * + * @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(); + } + + //---------------------------------------------------------------------------------------------- + + /** + * {@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(); + 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 { + // 写锁 + 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(); + } + + /** + * 转为读锁 + *

+ * 如果当前状态为写锁则会降级为读锁,否则不进行操作 + * + * @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 LOCK_STATE.get() != null && (LOCK_STATE.get() == 1 || LOCK_STATE.get() == 2); } + + /** + * 检查读锁是否被占用 + * + * @return 是否被占用 + * + * @since 0.1.0 + */ + public + boolean isReadLocked() { return LOCK_STATE.get() == 1; } + + /** + * 检查写锁是否被占用 + * + * @return 是否被占用 + * + * @since 0.1.0 + */ + public + boolean isWriteLocked() { return LOCK_STATE.get() == 2; } + + /** + * 获取读锁{@link Condition} + * + * @see ReentrantReadWriteLock.ReadLock#newCondition() + * @since 0.1.0 + */ + @NotNull + public + Condition newReadCondition() { return Read_LOCK.newCondition(); } - @Getter final private ReentrantReadWriteLock LOCK; - @Getter final private ReentrantReadWriteLock.ReadLock Read_LOCK; - @Getter final private ReentrantReadWriteLock.WriteLock Write_LOCK; - - public - RWLock() {this(false);} - - /** 生成并发管理,并指定是否使用公平锁 */ - public - RWLock(boolean fair) { - LOCK = new ReentrantReadWriteLock(false); - Read_LOCK = LOCK.readLock(); - Write_LOCK = LOCK.writeLock(); - } - - //---------------------------------------------------------------------------------------------- - - @Override - public - T read(@NotNull Supplier run) { - try { - Read_LOCK.lock(); - return run.get(); - } finally { - Read_LOCK.unlock(); - } - } - - @Override - public - T write(@NotNull Supplier run) { - try { - Write_LOCK.lock(); - return run.get(); - } finally { - Write_LOCK.unlock(); - } - } - - //---------------------------------------------------------------------------------------------- - - @Override - public - T tryread(@NotNull Class ecla, @NotNull trySupplier run) - throws E - { - try { - Read_LOCK.lock(); - return run.get(); - } finally { - Read_LOCK.unlock(); - } - } - - @Override - public - T trywrite(@NotNull Class ecla, @NotNull trySupplier run) - throws E - { - try { - Write_LOCK.lock(); - return run.get(); - } finally { - Write_LOCK.unlock(); - } - } - - //---------------------------------------------------------------------------------------------- - - /** 获取 {@link Condition} */ - @NotNull - public - Condition newReadCondition() {return Read_LOCK.newCondition();} - - /** 获取 {@link Condition} */ - @NotNull - public - Condition newWriteCondition() {return Write_LOCK.newCondition();} + /** + * 获取写锁{@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 b5208f0c8fdc25feccdf9afdf03f1ba7910d0512..02deb448788e21a8a8c7c03dd46376a019971f14 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/ReLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/ReLock.java @@ -1,100 +1,180 @@ package fybug.nulll.pdconcurrent; -import org.jetbrains.annotations.NotNull; - import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Supplier; +import java.util.function.Function; +import fybug.nulll.pdconcurrent.e.LockType; import fybug.nulll.pdconcurrent.fun.trySupplier; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; import lombok.Getter; /** - * 使用 {@link ReentrantLock} 实现的并发管理 - *

使用并发管理:
- *     public static
- *     void main(String[] args) {
- *         var lock = new ReLock();
- *         lock.read(() -> System.out.println("asdas"));
- *     }
- *
不使用:
- *     public static
- *     void main(String[] args) {
- *         var lock = new ReentrantLock();
- *         lock.lock();
- *         try {
- *             System.out.println("asdas");
- *         } finally {
- *             lock.unlock();
- *         }
- *     }
+ *

使用{@link ReentrantLock}实现的并发管理.

+ * 使用{@link ReentrantLock}实现并发域,读写锁均为同一个实现
+ * 使用了可中断的上锁操作{@link ReentrantLock#lockInterruptibly()}
+ * 支持使用{@link #newCondition()}获取{@link Condition},通过{@link #isLocked()}检查是否被占用 + *

+ * 使用并发管理: + * {@snippet lang = java: + * 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 static void main(String[] args) { + * var lock = new ReentrantLock(); + * lock.lock(); + * try { + * System.out.println("asdas"); + * } finally { + * lock.unlock(); + * } + * }} * * @author fybug - * @version 0.0.1 + * @version 0.1.0 + * @see SyLock + * @see ReentrantLock * @since PDConcurrent 0.0.1 */ +@Getter public class ReLock implements SyLock { - - // 锁 - @Getter private final ReentrantLock LOCK; - - public - ReLock() {this(false);} - - /** 构造并发处理,并决定使用公平锁还是非公平锁 */ - public - ReLock(boolean fair) { LOCK = new ReentrantLock(fair); } - - //---------------------------------------------------------------------------------------------- - - @Override - public - T read(@NotNull Supplier run) { return run(run); } - - @Override - public - T write(@NotNull Supplier run) { return run(run); } - - // 读写无区别 - private - T run(Supplier run) { - try { - LOCK.lock(); - return run.get(); - } finally { - LOCK.unlock(); - } - } - - //------------------------------------------ - - @Override - public - T tryread(@NotNull Class ecla, @NotNull trySupplier run) - throws E - { return tryrun(ecla, run); } - - @Override - public - T trywrite(@NotNull Class ecla, @NotNull trySupplier run) - throws E - { return tryrun(ecla, run); } - - // 读写无区别 - private - T tryrun(Class ecla, trySupplier run) throws E { - try { - LOCK.lock(); - return run.get(); - } finally { - LOCK.unlock(); - } - } - - //------------------------------------------- - - /** 获取 {@link Condition} */ - @NotNull - public - Condition newCondition() {return LOCK.newCondition();} + /** 锁 */ + private final ReentrantLock LOCK; + + /** + * 构建并发管理 + *

+ * 使用非公平锁 + */ + public + ReLock() { this(false); } + + /** + * 构造并发处理 + * + * @param fair 是否使用公平锁 + */ + public + ReLock(boolean fair) { this(new ReentrantLock(fair)); } + + /** + * 构造并发处理 + * + * @param LOCK 使用的锁 + * + * @since 0.1.0 + */ + public + ReLock(@NotNull ReentrantLock LOCK) { this.LOCK = LOCK; } + + //---------------------------------------------------------------------------------------------- + + /** + * {@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; + } + + /** + * {@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; + } + + //---------------------------------------------------------------------------------------------- + + /** + * 获取{@link Condition} + * + * @see ReentrantLock#newCondition() + */ + @NotNull + public + Condition newCondition() { return LOCK.newCondition(); } + + /** + * 检查锁是否被占用 + * + * @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 620ccc0f5c9c0fc7757d805b9fc8d5e18ac5114f..1d7929ac62976b1efc7460b38e0153a5c10c542f 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/SyLock.java +++ b/src/main/java/fybug/nulll/pdconcurrent/SyLock.java @@ -1,311 +1,515 @@ package fybug.nulll.pdconcurrent; -import org.jetbrains.annotations.NotNull; - import java.util.function.Consumer; -import java.util.function.Supplier; +import java.util.function.Function; +import fybug.nulll.pdconcurrent.e.LockType; import fybug.nulll.pdconcurrent.fun.tryRunnable; import fybug.nulll.pdconcurrent.fun.trySupplier; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; /** *

并发管理.

- * 通过使用接口运行的方式隐藏内部的并发管理方法
- * 让开发人员无需管理并发的具体方式
- * {@code **read()} 方法用于申请读取方法,{@code **write()} 用于申请写入方法,只有在使用读写锁实现 {@link RWLock} 才有区别。其余实现两个之间无区别
- * {@code try**()} 类型的方法为可抛出异常的方法,可在传入的接口中抛出异常,但是需要指定异常的类型
- * 也可在该类方法中传入 catch 块和 finally 块的代码,随后将不会抛出异常。发生异常后返回将会变为 {@code null} + * 通过传入回调的方式隐藏内部的并发管理方法,并支持复用内部的try块,通过传入的回调插入到catch,finally块中执行
+ * {@code **lock()} 方法用于根据传入的{@link LockType}申请不同的锁类型进行执行
+ * {@code **read()} 方法用于申请使用读锁,{@code **write()} 用于申请使用写锁,只有在使用读写锁实现 {@link RWLock} 才有区别。其余实现两个之间无区别
+ * {@code try**()} 类型的方法为可抛出异常的方法,可在传入的接口中抛出异常 *

* 使用 {@code new**Lock()} 的方法获取不同并发管理的实例
* * @author fybug - * @version 0.0.2 + * @version 0.1.0 + * @apiNote 并发控制通用接口,规定并实现大部分通用控制功能 * @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块后的回调 + * + * @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; + }); + } + + //----------------------------------------------- - /** - * 申请并运行于读锁 - * - * @param run 运行代码 - */ - default - void read(@NotNull Runnable run) { - read(() -> { - run.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); } - /** - * 申请并运行于写锁 - * - * @param run 运行代码 - */ - default - void write(@NotNull Runnable run) { - write(() -> { - run.run(); - return 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); + } - //------------------------------------ + //----------------------------------------------- - /** - * 申请并运行于读锁 - * - * @param run 带返回的运行代码 - * - * @return 接口生成的数据 - */ - T read(@NotNull Supplier run); + /** + * 尝试使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
+ * 所有回调均在并发域内执行 + * + * @param lockType 锁类型 + * @param run 带返回的回调 + * @param finaby 进入finally块后的回调,传入前一个回调的返回值,遇到异常传入{@code null} + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @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; - /** - * 申请并运行于写锁 - * - * @param run 带返回的运行代码 - * - * @return 接口生成的数据 - */ - T write(@NotNull Supplier run); + /** + * 尝试使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,通过两个回调参数插入不同的块中执行,遇到异常会抛出
+ * 所有回调均在并发域内执行 + * + * @param lockType 锁类型 + * @param run 执行的回调 + * @param finaby 进入finally块后的回调 + * + * @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; + }); + } - //---------------------------------------------------------------------------------------------- + //----------------------------------------------- - /** - * 尝试运行于读锁 - * - * @param ecla 异常的类 - * @param run 运行代码 - */ - default - void tryread(@NotNull Class ecla, @NotNull tryRunnable run) throws E - { - tryread(ecla, () -> { - run.run(); - return null; - }); - } + /** + * 尝试使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,遇到异常会抛出 + * + * @param lockType 锁类型 + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @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); } - /** - * 尝试运行于写锁 - * - * @param ecla 异常的类 - * @param run 运行代码 - */ - default - void trywrite(@NotNull Class ecla, @NotNull tryRunnable run) - throws E - { - trywrite(ecla, () -> { - run.run(); - return null; - }); - } + /** + * 尝试使用锁执行指定回调 + *

+ * 可通过传入{@link LockType}指定锁的类型,运行时自带try-finally块,遇到异常会抛出 + * + * @param lockType 锁类型 + * @param run 执行的回调 + * + * @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); + } - //------------------------------------ + /*--------------------------------------------------------------------------------------------*/ - /** - * 尝试运行于读锁 - * - * @param ecla 异常的类 - * @param run 带返回的运行代码 - * - * @return 接口生成的数据 - */ - T tryread(@NotNull Class ecla, @NotNull trySupplier run) - throws E; + /** + * 使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带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); } - /** - * 尝试运行于写锁 - * - * @param ecla 异常的类 - * @param run 带返回的运行代码 - * - * @return 接口生成的数据 - */ - T trywrite(@NotNull Class ecla, @NotNull trySupplier run) - throws E; + /** + * 使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带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 要返回的数据类型 + * + * @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); } - /** - * 尝试运行于读锁 - * - * @param ecla 异常的类 - * @param run 运行代码 - * @param cate 异常处理代码 - * - * @since SyLock 0.0.2 - */ - default - void tryread(@NotNull Class ecla, @NotNull tryRunnable run, - @NotNull Consumer cate) - { - tryread(ecla, () -> { - run.run(); - return null; - }, cate, () -> {}); - } + /** + * 使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带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); + } - /** - * 尝试运行于写锁 - * - * @param ecla 异常的类 - * @param run 运行代码 - * @param cate 异常处理代码 - * - * @since SyLock 0.0.2 - */ - default - void trywrite(@NotNull Class ecla, @NotNull tryRunnable run, - @NotNull Consumer cate) - { - trywrite(ecla, () -> { - run.run(); - return null; - }, cate, () -> {}); - } + //----------------------------------------------- - //------------------------------------ + /** + * 使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带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); } - /** - * 尝试运行于读锁 - * - * @param ecla 异常的类 - * @param run 带返回的运行代码 - * @param cate 异常处理代码 - * - * @return 接口生成的数据 - * - * @since SyLock 0.0.2 - */ - default - T tryread(@NotNull Class ecla, @NotNull trySupplier run, - @NotNull Consumer cate) - { return tryread(ecla, run, cate, () -> {}); } + /** + * 使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带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; + }); + } - /** - * 尝试运行于写锁 - * - * @param ecla 异常的类 - * @param run 带返回的运行代码 - * @param cate 异常处理代码 - * - * @return 接口生成的数据 - * - * @since SyLock 0.0.2 - */ - default - T trywrite(@NotNull Class ecla, @NotNull trySupplier run, - @NotNull Consumer cate) - { return trywrite(ecla, run, cate, () -> {}); } + /** + * 使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带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 执行的回调 + * @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; + }); + } - /** - * 尝试运行于读锁 - * - * @param ecla 异常的类 - * @param run 运行代码 - * @param cate 异常处理代码 - * - * @since SyLock 0.0.2 - */ - default - void tryread(@NotNull Class ecla, @NotNull tryRunnable run, - @NotNull Consumer cate, @NotNull Runnable finall) - { - tryread(ecla, () -> { - run.run(); - return null; - }, cate, finall); - } + //----------------------------------------------- - /** - * 尝试运行于写锁 - * - * @param ecla 异常的类 - * @param run 运行代码 - * @param cate 异常处理代码 - * - * @since SyLock 0.0.2 - */ - default - void trywrite(@NotNull Class ecla, @NotNull tryRunnable run, - @NotNull Consumer cate, @NotNull Runnable finall) - { - trywrite(ecla, () -> { - run.run(); - return null; - }, cate, finall); - } + /** + * 尝试使用读锁执行指定回调 + *

+ * 调用读锁执行,运行时自带try-finally块,遇到异常会抛出 + * + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @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 执行的回调 + * + * @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); + } - /** - * 尝试运行于读锁 - * - * @param ecla 异常的类 - * @param run 带返回的运行代码 - * @param cate 异常处理代码 - * @param finall finally 块处理代码 - * - * @return 接口生成的数据 - * - * @since SyLock 0.0.2 - */ - default - T tryread(@NotNull Class ecla, @NotNull trySupplier run, - @NotNull Consumer cate, @NotNull Runnable finall) - { - try { - return tryread(ecla, run); - } catch ( Exception e ) { - cate.accept((E) e); - return null; - } finally { - finall.run(); - } - } + /** + * 尝试使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-finally块,遇到异常会抛出 + * + * @param run 带返回的回调 + * @param 要返回的数据类型 + * + * @return 回调返回的内容,遇到异常不返回 + * + * @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); } - /** - * 尝试运行于写锁 - * - * @param ecla 异常的类 - * @param run 带返回的运行代码 - * @param cate 异常处理代码 - * @param finall finally 块处理代码 - * - * @return 接口生成的数据 - * - * @since SyLock 0.0.2 - */ - default - T trywrite(@NotNull Class ecla, @NotNull trySupplier run, - @NotNull Consumer cate, @NotNull Runnable finall) - { - try { - return trywrite(ecla, run); - } catch ( Exception e ) { - cate.accept((E) e); - return null; - } finally { - finall.run(); - } - } + /** + * 尝试使用写锁执行指定回调 + *

+ * 调用写锁执行,运行时自带try-finally块,遇到异常会抛出 + * + * @param run 执行的回调 + * + * @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); + } - /*--------------------------------------------------------------------------------------------*/ + /*--------------------------------------------------------------------------------------------*/ - /** 获取传统并发实现 */ - static @NotNull - ObjLock newObjLock() {return new ObjLock();} + /** + * 获取传统并发实现 + * + * @see ObjLock + */ + @NotNull + static + ObjLock newObjLock() { return new ObjLock(); } - /** 获取 Lock 实现 */ - static @NotNull - ReLock newReLock() {return new ReLock();} + /** + * 获取可重入锁实现 + * + * @see ReLock + */ + @NotNull + static + ReLock newReLock() { return new ReLock(); } - /** 获取读写锁实现 */ - static @NotNull - RWLock newRWLock() {return new RWLock();} + /** + * 获取读写锁实现 + * + * @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 new file mode 100644 index 0000000000000000000000000000000000000000..0d722ea273db811863a73af8443091d55bac7a1b --- /dev/null +++ b/src/main/java/fybug/nulll/pdconcurrent/e/LockType.java @@ -0,0 +1,18 @@ +package fybug.nulll.pdconcurrent.e; + +/** + *

锁类型.

+ * + * @author fybug + * @version 0.0.1 + * @since PDConcurrent 0.1.0 + */ +public +enum LockType { + /** 读锁 */ + READ, + /** 写锁 */ + WRITE, + /** 不上锁 */ + NOLOCK +} diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/package-info.java b/src/main/java/fybug/nulll/pdconcurrent/fun/package-info.java index 3034641e034c3d644552f82a4d71215b5d12983f..67680b723059e6f53ffc398616014843f534e497 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/package-info.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/package-info.java @@ -2,7 +2,7 @@ * 功能接口包 * * @author fybug - * @version 0.0.2 + * @version 0.0.4 * @since PDConcurrent 0.0.1 */ package fybug.nulll.pdconcurrent.fun; \ No newline at end of file diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/tryBiConsumer.java b/src/main/java/fybug/nulll/pdconcurrent/fun/tryBiConsumer.java deleted file mode 100644 index 291bc82d15370cbde79a4e75ec43f0621f75b4c7..0000000000000000000000000000000000000000 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryBiConsumer.java +++ /dev/null @@ -1,14 +0,0 @@ -package fybug.nulll.pdconcurrent.fun; -import java.util.function.BiConsumer; - -/** - * @author fybug - * @version 0.0.1 - * @see BiConsumer - * @since fun 0.0.1 - */ -@FunctionalInterface -public -interface tryBiConsumer { - void accept(T t, U u) throws E; -} diff --git a/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java b/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java index 974937105568235ec09b754e0ba9d95071abc475..b3ba660ba278183bffead0595d8df4653ceec73d 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/tryConsumer.java @@ -1,14 +1,46 @@ package fybug.nulll.pdconcurrent.fun; import java.util.function.Consumer; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + /** * @author fybug - * @version 0.0.1 + * @version 0.0.2 * @see Consumer - * @since fun 0.0.1 + * @since fun 0.0.4 */ -@FunctionalInterface public -interface tryConsumer { - void accept(T t) throws E; +interface tryConsumer { + /** @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 + 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 2c515ad40737dce4375bf5e829403201c63f000a..060841ce89b8f0d01861fc8ba388be747cfa72c3 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/tryFunction.java @@ -1,14 +1,35 @@ package fybug.nulll.pdconcurrent.fun; import java.util.function.Function; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + /** * @author fybug - * @version 0.0.1 + * @version 0.0.2 * @see Function - * @since fun 0.0.1 + * @since fun 0.0.4 */ -@FunctionalInterface public -interface tryFunction { - R apply(T t) throws E; +interface tryFunction { + /** @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 + 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 c5ae5eaef15d53c848e558191a7223da63646d8b..970eeacf5601ed361df08aaee1baf8d42b88b7aa 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/tryRunnable.java @@ -1,13 +1,74 @@ package fybug.nulll.pdconcurrent.fun; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; /** * @author fybug - * @version 0.0.1 + * @version 0.0.2 * @see Runnable - * @since fun 0.0.2 + * @since fun 0.0.4 */ @FunctionalInterface public -interface tryRunnable { - void run() throws E; +interface tryRunnable { + /** @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 + 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 + 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 81a193b6b08aa07ef5a2f2d28c469c7dcae02a52..1733f2485bd31b2c96721e0e41b24884ce8e2821 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java +++ b/src/main/java/fybug/nulll/pdconcurrent/fun/trySupplier.java @@ -1,14 +1,36 @@ package fybug.nulll.pdconcurrent.fun; import java.util.function.Supplier; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + /** * @author fybug - * @version 0.0.1 + * @version 0.0.2 * @see Supplier - * @since fun 0.0.1 + * @since fun 0.0.4 */ @FunctionalInterface public -interface trySupplier { - V get() throws E; +interface trySupplier { + /** @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 + 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 dbe9cc79f8fe3208c95c2c7b6da6e26878098aa3..640060ae19b852a6dc78aafd430b0b72bef8dd31 100644 --- a/src/main/java/fybug/nulll/pdconcurrent/package-info.java +++ b/src/main/java/fybug/nulll/pdconcurrent/package-info.java @@ -1,11 +1,11 @@ /** *

并发管理工具.

- * 用于并发管理的工具,使用接口在并发域中执行代码。
- * 根据实现的不同并发管理也不同,但都实现 {@link fybug.nulll.pdconcurrent.SyLock} 接口
- * 附带 {@code try***} 的功能接口包,在 java 原有的功能接口的基础上允许抛出异常 + * 用于并发管理的工具,使用回调在并发域中执行代码。
+ * 根据实现的不同并发管理也不同,但都实现{@link fybug.nulll.pdconcurrent.SyLock}接口
+ * 附带{@code try***}的功能接口包{@link fybug.nulll.pdconcurrent.fun},在java原有的功能接口的基础上允许抛出异常 * * @author fybug - * @version 0.0.1 - * @since JDK 13+ + * @version 0.1.0 + * @since JDK 23+ */ package fybug.nulll.pdconcurrent; \ No newline at end of file