mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix pool
This commit is contained in:
parent
65fd58e690
commit
1fa28d6fde
@ -18,18 +18,13 @@ package org.dromara.hutool.core.collection;
|
||||
|
||||
|
||||
import org.dromara.hutool.core.collection.set.SetUtil;
|
||||
import org.dromara.hutool.core.func.SerFunction;
|
||||
import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.map.MapUtil;
|
||||
import org.dromara.hutool.core.stream.CollectorUtil;
|
||||
import org.dromara.hutool.core.stream.StreamUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collector;
|
||||
@ -53,7 +48,7 @@ public class CollStreamUtil {
|
||||
* @param <K> map中的key类型
|
||||
* @return 转化后的map
|
||||
*/
|
||||
public static <V, K> Map<K, V> toIdentityMap(final Collection<V> collection, final Function<V, K> key) {
|
||||
public static <V, K> Map<K, V> toIdentityMap(final Collection<V> collection, final SerFunction<V, K> key) {
|
||||
return toIdentityMap(collection, key, false);
|
||||
}
|
||||
|
||||
@ -69,7 +64,7 @@ public class CollStreamUtil {
|
||||
* @param <K> map中的key类型
|
||||
* @return 转化后的map
|
||||
*/
|
||||
public static <V, K> Map<K, V> toIdentityMap(final Collection<V> collection, final Function<V, K> key, final boolean isParallel) {
|
||||
public static <V, K> Map<K, V> toIdentityMap(final Collection<V> collection, final SerFunction<V, K> key, final boolean isParallel) {
|
||||
if (CollUtil.isEmpty(collection)) {
|
||||
return MapUtil.zero();
|
||||
}
|
||||
@ -230,8 +225,8 @@ public class CollStreamUtil {
|
||||
* @param <V> List中的value类型
|
||||
* @return 分组后的map
|
||||
*/
|
||||
public static <E, K, V> Map<K, List<V>> groupKeyValue(final Collection<E> collection, final Function<E, K> key,
|
||||
final Function<E, V> value) {
|
||||
public static <E, K, V> Map<K, List<V>> groupKeyValue(final Collection<E> collection, final SerFunction<E, K> key,
|
||||
final SerFunction<E, V> value) {
|
||||
return groupKeyValue(collection, key, value, false);
|
||||
}
|
||||
|
||||
@ -248,8 +243,8 @@ public class CollStreamUtil {
|
||||
* @param <V> List中的value类型
|
||||
* @return 分组后的map
|
||||
*/
|
||||
public static <E, K, V> Map<K, List<V>> groupKeyValue(final Collection<E> collection, final Function<E, K> key,
|
||||
final Function<E, V> value, final boolean isParallel) {
|
||||
public static <E, K, V> Map<K, List<V>> groupKeyValue(final Collection<E> collection, final SerFunction<E, K> key,
|
||||
final SerFunction<E, V> value, final boolean isParallel) {
|
||||
if (CollUtil.isEmpty(collection)) {
|
||||
return MapUtil.zero();
|
||||
}
|
||||
|
@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.dromara.hutool.core.lang;
|
||||
|
||||
import org.dromara.hutool.core.func.SerConsumer;
|
||||
import org.dromara.hutool.core.func.SerFunction;
|
||||
import org.dromara.hutool.core.func.SerPredicate;
|
||||
import org.dromara.hutool.core.func.SerSupplier;
|
||||
import org.dromara.hutool.core.stream.EasyStream;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
@ -27,7 +30,6 @@ import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
@ -128,7 +130,7 @@ public class Opt<T> {
|
||||
* @since 6.0.0
|
||||
*/
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
public static <T> Opt<T> of(final Optional<T> optional) {
|
||||
public static <T> Opt<T> of(final Optional<? extends T> optional) {
|
||||
return ofNullable(optional.orElse(null));
|
||||
}
|
||||
|
||||
@ -166,7 +168,6 @@ public class Opt<T> {
|
||||
* 判断包裹里元素的值是否不存在,不存在为 {@code true},否则为{@code false}
|
||||
*
|
||||
* @return 包裹里元素的值不存在 则为 {@code true},否则为{@code false}
|
||||
* @since 11 这是jdk11{@link java.util.Optional}中的新函数
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return value == null;
|
||||
@ -261,74 +262,59 @@ public class Opt<T> {
|
||||
* @return this
|
||||
* @throws NullPointerException 如果包裹里的值存在,但你传入的操作为{@code null}时抛出
|
||||
*/
|
||||
public Opt<T> ifPresent(final Consumer<? super T> action) {
|
||||
public Opt<T> ifPresent(final SerConsumer<? super T> action) {
|
||||
if (isPresent()) {
|
||||
action.accept(value);
|
||||
try {
|
||||
action.accepting(value);
|
||||
} catch (final Throwable e) {
|
||||
this.throwable = e;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断包裹里的值存在并且与给定的条件是否满足 ({@link Predicate#test}执行结果是否为true)
|
||||
* 如果满足条件则返回本身
|
||||
* 不满足条件或者元素本身为空时返回一个返回一个空的{@code Opt}
|
||||
* 如果满足条件则返回本身<br>
|
||||
* 不满足条件或者元素本身为空时返回一个返回一个空的{@code Opt}<br>
|
||||
* predicate测试报错,则返回一个空的{@code Opt},并附带错误信息
|
||||
*
|
||||
* @param predicate 给定的条件
|
||||
* @return 如果满足条件则返回本身, 不满足条件或者元素本身为空时返回一个空的{@code Opt}
|
||||
* @throws NullPointerException 如果给定的条件为 {@code null}抛出{@code NPE}
|
||||
*/
|
||||
public Opt<T> filter(final Predicate<? super T> predicate) {
|
||||
public Opt<T> filter(final SerPredicate<? super T> predicate) {
|
||||
Objects.requireNonNull(predicate);
|
||||
if (isEmpty() || isFail()) {
|
||||
return this;
|
||||
} else {
|
||||
return predicate.test(value) ? this : empty();
|
||||
}
|
||||
|
||||
try {
|
||||
return predicate.testing(value) ? this : empty();
|
||||
} catch (final Throwable e) {
|
||||
return createError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果包裹里的值存在,就执行传入的操作({@link Function#apply})并返回一个包裹了该操作返回值的{@code Opt}
|
||||
* 如果包裹里的值存在,就执行传入的操作({@link SerFunction#applying(Object)})并返回一个包裹了该操作返回值的{@code Opt}
|
||||
* 如果不存在,返回一个空的{@code Opt}
|
||||
*
|
||||
* @param mapper 值存在时执行的操作
|
||||
* @param <U> 操作返回值的类型
|
||||
* @return 如果包裹里的值存在,就执行传入的操作({@link Function#apply})并返回一个包裹了该操作返回值的{@code Opt},
|
||||
* @return 如果包裹里的值存在,就执行传入的操作({@link SerFunction#applying(Object)})并返回一个包裹了该操作返回值的{@code Opt},
|
||||
* 如果不存在,返回一个空的{@code Opt}
|
||||
* @throws NullPointerException 如果给定的操作为 {@code null},抛出 {@code NPE}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <U> Opt<U> map(final Function<? super T, ? extends U> mapper) {
|
||||
public <U> Opt<U> map(final SerFunction<? super T, ? extends U> mapper) {
|
||||
Objects.requireNonNull(mapper);
|
||||
if (isFail()) {
|
||||
return (Opt<U>) this;
|
||||
} else if (isEmpty()) {
|
||||
return empty();
|
||||
} else {
|
||||
return Opt.ofNullable(mapper.apply(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果包裹里的值存在,就执行传入的操作({@link Function#apply})并返回该操作返回值
|
||||
* 如果不存在,返回一个空的{@code Opt}
|
||||
* 和 {@link Opt#map}的区别为 传入的操作返回值必须为 Opt
|
||||
*
|
||||
* @param mapper 值存在时执行的操作
|
||||
* @param <U> 操作返回值的类型
|
||||
* @return 如果包裹里的值存在,就执行传入的操作({@link Function#apply})并返回该操作返回值
|
||||
* 如果不存在,返回一个空的{@code Opt}
|
||||
* @throws NullPointerException 如果给定的操作为 {@code null}或者给定的操作执行结果为 {@code null},抛出 {@code NPE}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <U> Opt<U> flatMap(final Function<? super T, ? extends Opt<? extends U>> mapper) {
|
||||
Objects.requireNonNull(mapper);
|
||||
if (isFail()) {
|
||||
return (Opt<U>) this;
|
||||
} else if (isEmpty()) {
|
||||
return empty();
|
||||
} else {
|
||||
@SuppressWarnings("unchecked") final Opt<U> r = (Opt<U>) mapper.apply(value);
|
||||
return Objects.requireNonNull(r);
|
||||
return Opt.ofTry(() -> mapper.applying(value));
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,39 +332,28 @@ public class Opt<T> {
|
||||
* @since 5.7.16
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <U> Opt<U> flattedMap(final Function<? super T, ? extends Optional<? extends U>> mapper) {
|
||||
public <U> Opt<U> flattedMap(final SerFunction<? super T, ? extends Optional<? extends U>> mapper) {
|
||||
Objects.requireNonNull(mapper);
|
||||
if (isFail()) {
|
||||
return (Opt<U>) this;
|
||||
} else if (isEmpty()) {
|
||||
return empty();
|
||||
} else {
|
||||
return ofNullable(mapper.apply(value).orElse(null));
|
||||
final Optional<? extends U> optional;
|
||||
try {
|
||||
optional = mapper.applying(value);
|
||||
} catch (final Throwable e) {
|
||||
return createError(e);
|
||||
}
|
||||
return of(optional);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果包裹里元素的值存在,就执行对应的操作,并返回本身
|
||||
* 如果不存在,返回一个空的{@code Opt}
|
||||
*
|
||||
* <p>属于 {@link #ifPresent}的链式拓展
|
||||
*
|
||||
* @param action 值存在时执行的操作
|
||||
* @return this
|
||||
* @throws NullPointerException 如果值存在,并且传入的操作为 {@code null}
|
||||
* @author VampireAchao
|
||||
*/
|
||||
public Opt<T> peek(final Consumer<T> action) throws NullPointerException {
|
||||
return ifPresent(action);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 如果包裹里元素的值存在,就执行对应的操作集,并返回本身
|
||||
* 如果不存在,返回一个空的{@code Opt}
|
||||
*
|
||||
* <p>属于 {@link #ifPresent}的链式拓展
|
||||
* <p>属于 {@link #peek(Consumer)}的动态拓展
|
||||
* <p>属于 {@link #ifPresent(SerConsumer)}的动态拓展
|
||||
*
|
||||
* @param actions 值存在时执行的操作,动态参数,可传入数组,当数组为一个空数组时并不会抛出 {@code NPE}
|
||||
* @return this
|
||||
@ -386,9 +361,8 @@ public class Opt<T> {
|
||||
* @author VampireAchao
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final Opt<T> peeks(final Consumer<T>... actions) throws NullPointerException {
|
||||
return peek(Stream.of(actions).reduce(Consumer::andThen).orElseGet(() -> o -> {
|
||||
}));
|
||||
public final Opt<T> ifPresents(final SerConsumer<T>... actions) throws NullPointerException {
|
||||
return ifPresent(Stream.of(actions).reduce(SerConsumer::andThen).orElseGet(() -> o -> {}));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -398,7 +372,7 @@ public class Opt<T> {
|
||||
* @return 如果包裹里元素的值存在,就返回本身,如果不存在,则使用传入的函数执行后获得的 {@code Opt}
|
||||
* @throws NullPointerException 如果传入的操作为空,或者传入的操作执行后返回值为空,则抛出 {@code NPE}
|
||||
*/
|
||||
public Opt<T> or(final Supplier<? extends Opt<? extends T>> supplier) {
|
||||
public Opt<T> or(final SerSupplier<? extends Opt<? extends T>> supplier) {
|
||||
Objects.requireNonNull(supplier);
|
||||
if (isPresent()) {
|
||||
return this;
|
||||
@ -456,7 +430,7 @@ public class Opt<T> {
|
||||
* @return 如果包裹里元素的值存在,则返回该值,否则返回传入的操作执行后的返回值
|
||||
* @throws NullPointerException 如果之不存在,并且传入的操作为空,则抛出 {@code NPE}
|
||||
*/
|
||||
public T orElseGet(final Supplier<? extends T> supplier) {
|
||||
public T orElseGet(final SerSupplier<? extends T> supplier) {
|
||||
return isPresent() ? value : supplier.get();
|
||||
}
|
||||
|
||||
@ -467,7 +441,7 @@ public class Opt<T> {
|
||||
* @return 如果包裹里元素的值存在,则返回该值,否则返回传入的操作执行后的返回值
|
||||
* @throws NullPointerException 如果之不存在,并且传入的操作为空,则抛出 {@code NPE}
|
||||
*/
|
||||
public Opt<T> orElseOpt(final Supplier<? extends T> supplier) {
|
||||
public Opt<T> orElseOpt(final SerSupplier<? extends T> supplier) {
|
||||
return or(() -> ofNullable(supplier.get()));
|
||||
}
|
||||
|
||||
@ -507,7 +481,7 @@ public class Opt<T> {
|
||||
* @throws X 如果值不存在
|
||||
* @throws NullPointerException 如果值不存在并且 传入的操作为 {@code null}或者操作执行后的返回值为{@code null}
|
||||
*/
|
||||
public <X extends Throwable> T orElseThrow(final Supplier<? extends X> exceptionSupplier) throws X {
|
||||
public <X extends Throwable> T orElseThrow(final SerSupplier<? extends X> exceptionSupplier) throws X {
|
||||
if (isPresent()) {
|
||||
return value;
|
||||
} else {
|
||||
@ -581,4 +555,17 @@ public class Opt<T> {
|
||||
public String toString() {
|
||||
return StrUtil.toStringOrNull(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建空的带异常的Opt
|
||||
*
|
||||
* @param throwable 异常
|
||||
* @param <T> 类型
|
||||
* @return Opt
|
||||
*/
|
||||
private static <T> Opt<T> createError(final Throwable throwable) {
|
||||
final Opt<T> emptyWithError = new Opt<>(null);
|
||||
emptyWithError.throwable = throwable;
|
||||
return emptyWithError;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.dromara.hutool.core.lang.range;
|
||||
|
||||
import org.dromara.hutool.core.func.SerPredicate;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
|
||||
import java.util.Objects;
|
||||
@ -60,7 +61,8 @@ import java.util.function.Predicate;
|
||||
* @see Bound
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class BoundedRange<T extends Comparable<? super T>> implements Predicate<T> {
|
||||
public class BoundedRange<T extends Comparable<? super T>> implements SerPredicate<T> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 双向无界的区间
|
||||
@ -93,9 +95,9 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
Objects.requireNonNull(lowerBound);
|
||||
Objects.requireNonNull(upperBound);
|
||||
return checkEmpty(
|
||||
new BoundedRange<>(
|
||||
Bound.atLeast(lowerBound), Bound.atMost(upperBound)
|
||||
)
|
||||
new BoundedRange<>(
|
||||
Bound.atLeast(lowerBound), Bound.atMost(upperBound)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -113,7 +115,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
Objects.requireNonNull(lowerBound);
|
||||
Objects.requireNonNull(upperBound);
|
||||
return checkEmpty(
|
||||
new BoundedRange<>(Bound.greaterThan(lowerBound), Bound.lessThan(upperBound))
|
||||
new BoundedRange<>(Bound.greaterThan(lowerBound), Bound.lessThan(upperBound))
|
||||
);
|
||||
}
|
||||
|
||||
@ -131,10 +133,10 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
Objects.requireNonNull(lowerBound);
|
||||
Objects.requireNonNull(upperBound);
|
||||
return checkEmpty(
|
||||
new BoundedRange<>(
|
||||
Bound.atLeast(lowerBound),
|
||||
Bound.lessThan(upperBound)
|
||||
)
|
||||
new BoundedRange<>(
|
||||
Bound.atLeast(lowerBound),
|
||||
Bound.lessThan(upperBound)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -152,10 +154,10 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
Objects.requireNonNull(lowerBound);
|
||||
Objects.requireNonNull(upperBound);
|
||||
return checkEmpty(
|
||||
new BoundedRange<>(
|
||||
Bound.greaterThan(lowerBound),
|
||||
Bound.atMost(upperBound)
|
||||
)
|
||||
new BoundedRange<>(
|
||||
Bound.greaterThan(lowerBound),
|
||||
Bound.atMost(upperBound)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -315,8 +317,8 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
}
|
||||
// 上界小于下界时为空
|
||||
return compareValue > 0
|
||||
// 上下界的边界值相等,且不为退化区间是为空
|
||||
|| !(low.getType().isClose() && up.getType().isClose());
|
||||
// 上下界的边界值相等,且不为退化区间是为空
|
||||
|| !(low.getType().isClose() && up.getType().isClose());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -369,7 +371,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
*/
|
||||
public boolean isSuperset(final BoundedRange<T> other) {
|
||||
return getLowerBound().compareTo(other.getLowerBound()) <= 0
|
||||
&& getUpperBound().compareTo(other.getUpperBound()) >= 0;
|
||||
&& getUpperBound().compareTo(other.getUpperBound()) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -380,7 +382,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
*/
|
||||
public boolean isProperSuperset(final BoundedRange<T> other) {
|
||||
return getLowerBound().compareTo(other.getLowerBound()) < 0
|
||||
&& getUpperBound().compareTo(other.getUpperBound()) > 0;
|
||||
&& getUpperBound().compareTo(other.getUpperBound()) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -391,7 +393,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
*/
|
||||
public boolean isSubset(final BoundedRange<T> other) {
|
||||
return getLowerBound().compareTo(other.getLowerBound()) >= 0
|
||||
&& getUpperBound().compareTo(other.getUpperBound()) <= 0;
|
||||
&& getUpperBound().compareTo(other.getUpperBound()) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,7 +404,7 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
*/
|
||||
public boolean isProperSubset(final BoundedRange<T> other) {
|
||||
return getLowerBound().compareTo(other.getLowerBound()) > 0
|
||||
&& getUpperBound().compareTo(other.getUpperBound()) < 0;
|
||||
&& getUpperBound().compareTo(other.getUpperBound()) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -432,10 +434,10 @@ public class BoundedRange<T extends Comparable<? super T>> implements Predicate<
|
||||
* @return 是否
|
||||
*/
|
||||
@Override
|
||||
public boolean test(final T value) {
|
||||
public boolean testing(final T value) {
|
||||
return getLowerBound()
|
||||
.and(getUpperBound())
|
||||
.test(value);
|
||||
.and(getUpperBound())
|
||||
.test(value);
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
@ -24,8 +24,9 @@ import java.io.Serializable;
|
||||
* <ul>
|
||||
* <li>{@link #borrowObject()} 对象借出。</li>
|
||||
* <li>{@link #returnObject(Poolable)}对象归还。</li>
|
||||
* <li>{@link #free(Poolable)} 对象销毁。</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* 对于对象池中对象维护,通过{@link PoolConfig#getMaxIdle()}控制,规则如下:
|
||||
* <ul>
|
||||
* <li>如果借出量很多,则不断扩容,直到达到{@link PoolConfig#getMaxSize()}</li>
|
||||
@ -49,7 +50,7 @@ public interface ObjectPool<T> extends Closeable, Serializable {
|
||||
*
|
||||
* @return 对象
|
||||
*/
|
||||
Poolable<T> borrowObject();
|
||||
T borrowObject();
|
||||
|
||||
/**
|
||||
* 归还对象,流程如下:
|
||||
@ -62,7 +63,15 @@ public interface ObjectPool<T> extends Closeable, Serializable {
|
||||
* @param obj 对象
|
||||
* @return this
|
||||
*/
|
||||
ObjectPool<T> returnObject(final Poolable<T> obj);
|
||||
ObjectPool<T> returnObject(final T obj);
|
||||
|
||||
/**
|
||||
* 释放对象,即在使用中发现对象损坏或不可用,则直接销毁之
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return this
|
||||
*/
|
||||
ObjectPool<T> free(final T obj);
|
||||
|
||||
/**
|
||||
* 获取持有对象总数(包括空闲对象 + 正在使用对象数)
|
||||
|
@ -27,16 +27,26 @@ import org.dromara.hutool.core.lang.wrapper.Wrapper;
|
||||
public interface Poolable<T> extends Wrapper<T> {
|
||||
|
||||
/**
|
||||
* 获取最后借出时间
|
||||
* 获取对象空闲时长,单位:毫秒<br>
|
||||
* 空闲时间指在池中的时间,即借出时间到上次归还时间的差
|
||||
*
|
||||
* @return 空闲毫秒数
|
||||
*/
|
||||
default long getIdle() {
|
||||
return System.currentTimeMillis() - getLastReturn();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后归还时间
|
||||
*
|
||||
* @return 最后借出时间
|
||||
*/
|
||||
long getLastBorrow();
|
||||
long getLastReturn();
|
||||
|
||||
/**
|
||||
* 设置最后借出时间,在成功借出此对象时更新时间
|
||||
* 设置最后归还时间,在成功归还此对象时更新时间
|
||||
*
|
||||
* @param lastBorrow 最后借出时间
|
||||
* @param lastReturn 最后归还时间
|
||||
*/
|
||||
void setLastBorrow(final long lastBorrow);
|
||||
void setLastReturn(final long lastReturn);
|
||||
}
|
||||
|
@ -92,18 +92,25 @@ public class PartitionObjectPool<T> implements ObjectPool<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Poolable<T> borrowObject() {
|
||||
public T borrowObject() {
|
||||
checkClosed();
|
||||
return this.partitions[getPartitionIndex(this.config)].borrowObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartitionObjectPool<T> returnObject(final Poolable<T> obj) {
|
||||
public PartitionObjectPool<T> returnObject(final T obj) {
|
||||
checkClosed();
|
||||
this.partitions[getPartitionIndex(this.config)].returnObject(obj);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPool<T> free(final T obj) {
|
||||
checkClosed();
|
||||
this.partitions[getPartitionIndex(this.config)].free(obj);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.closed = true;
|
||||
|
@ -50,16 +50,16 @@ public class PartitionPoolable<T> implements Poolable<T> {
|
||||
* 归还对象
|
||||
*/
|
||||
public void returnObject() {
|
||||
this.partition.returnObject(this);
|
||||
this.partition.returnObject(this.getRaw());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastBorrow() {
|
||||
public long getLastReturn() {
|
||||
return lastBorrow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastBorrow(final long lastBorrow) {
|
||||
this.lastBorrow = lastBorrow;
|
||||
public void setLastReturn(final long lastReturn) {
|
||||
this.lastBorrow = lastReturn;
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* 初始化时创建{@link PoolConfig#getMinSize()}个对象作为初始池对象.
|
||||
*
|
||||
* <p>
|
||||
* 当借出对象时,从队列头部取出并验证,验证通过后使用,验证不通过直接调用{@link #free(Poolable)} 销毁并重新获取,
|
||||
* 当借出对象时,从队列头部取出并验证,验证通过后使用,验证不通过直接调用{@link #free(Object)} 销毁并重新获取,
|
||||
* 当池中对象都被借出(空了),创建新的对象并入队列,直到队列满为止,当满时等待归还,超时则报错。
|
||||
* </p>
|
||||
*
|
||||
@ -64,36 +64,33 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
||||
this.queue = queue;
|
||||
this.objectFactory = objectFactory;
|
||||
|
||||
final int minSize = config.getMinSize();
|
||||
for (int i = 0; i < minSize; i++) {
|
||||
queue.add(createPoolable());
|
||||
}
|
||||
total = minSize;
|
||||
// 初始化,按照配置最小大小创建对象
|
||||
doIncrease(config.getMinSize());
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@Override
|
||||
public Poolable<T> borrowObject() {
|
||||
public T borrowObject() {
|
||||
// 非阻塞获取
|
||||
Poolable<T> poolable = this.queue.poll();
|
||||
if (null != poolable) {
|
||||
final T obj = poolable.getRaw();
|
||||
// 检查对象是否可用
|
||||
if (this.objectFactory.validate(poolable.getRaw())) {
|
||||
if (this.objectFactory.validate(obj)) {
|
||||
// 检查是否超过最长空闲时间
|
||||
final long maxIdle = this.config.getMaxIdle();
|
||||
if (maxIdle <= 0 || (System.currentTimeMillis() - poolable.getLastBorrow()) <= maxIdle) {
|
||||
poolable.setLastBorrow(System.currentTimeMillis());
|
||||
return poolable;
|
||||
if (maxIdle <= 0 || poolable.getIdle() <= maxIdle) {
|
||||
return poolable.getRaw();
|
||||
}
|
||||
}
|
||||
|
||||
// 对象不可用,销毁之
|
||||
free(poolable);
|
||||
// 对象不可用或超过最长空闲期,销毁之
|
||||
free(obj);
|
||||
// 继续借,而不扩容
|
||||
return borrowObject();
|
||||
}
|
||||
|
||||
// 扩容
|
||||
// 池中无对象,扩容
|
||||
if (increase(1) <= 0) {
|
||||
// 池分区已满,只能等待是否有返还的对象
|
||||
poolable = waitingPoll();
|
||||
@ -111,22 +108,22 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
||||
/**
|
||||
* 归还对象
|
||||
*
|
||||
* @param poolable 归还的对象
|
||||
* @param obj 归还的对象
|
||||
* @return this
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
@Override
|
||||
public PoolPartition<T> returnObject(final Poolable<T> poolable) {
|
||||
public PoolPartition<T> returnObject(final T obj) {
|
||||
// 检查对象可用性
|
||||
if (this.objectFactory.validate(poolable.getRaw())) {
|
||||
if (this.objectFactory.validate(obj)) {
|
||||
try {
|
||||
this.queue.put(poolable);
|
||||
this.queue.put(wrapPoolable(obj));
|
||||
} catch (final InterruptedException e) {
|
||||
throw new PoolException(e);
|
||||
}
|
||||
} else {
|
||||
// 对象不可用
|
||||
free(poolable);
|
||||
free(obj);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -139,20 +136,8 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
||||
* @param increaseSize 扩容大小
|
||||
* @return 实际扩容大小,0表示已经达到最大,未成功扩容
|
||||
*/
|
||||
public synchronized int increase(int increaseSize) {
|
||||
if (increaseSize + total > config.getMaxSize()) {
|
||||
increaseSize = config.getMaxSize() - total;
|
||||
}
|
||||
|
||||
try {
|
||||
for (int i = 0; i < increaseSize; i++) {
|
||||
queue.put(createPoolable());
|
||||
}
|
||||
total += increaseSize;
|
||||
} catch (final InterruptedException e) {
|
||||
throw new PoolException(e);
|
||||
}
|
||||
return increaseSize;
|
||||
public synchronized int increase(final int increaseSize) {
|
||||
return doIncrease(increaseSize);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,8 +146,9 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
||||
* @param obj 被销毁的对象
|
||||
* @return this
|
||||
*/
|
||||
public synchronized PoolPartition<T> free(final Poolable<T> obj) {
|
||||
objectFactory.destroy(obj.getRaw());
|
||||
@Override
|
||||
public synchronized PoolPartition<T> free(final T obj) {
|
||||
objectFactory.destroy(obj);
|
||||
total--;
|
||||
return this;
|
||||
}
|
||||
@ -183,10 +169,11 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.queue.forEach(this::free);
|
||||
synchronized public void close() throws IOException {
|
||||
this.queue.forEach((poolable) -> objectFactory.destroy(poolable.getRaw()));
|
||||
this.queue.clear();
|
||||
this.queue = null;
|
||||
this.total = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -194,13 +181,45 @@ public class PoolPartition<T> implements ObjectPool<T> {
|
||||
*
|
||||
* @return {@link PartitionPoolable}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Poolable<T> createPoolable() {
|
||||
final T t = objectFactory.create();
|
||||
return null == t ? null : wrapPoolable(t);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Poolable<T> wrapPoolable(final T t) {
|
||||
if (t instanceof Poolable) {
|
||||
return (Poolable<T>) t;
|
||||
}
|
||||
return new PartitionPoolable<>(objectFactory.create(), this);
|
||||
return new PartitionPoolable<>(t, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 非线程安全的扩容并填充对象池队列<br>
|
||||
* 如果传入的扩容大小大于可用大小(即扩容大小加现有大小大于最大大小,则实际扩容到最大)
|
||||
*
|
||||
* @param increaseSize 扩容大小
|
||||
* @return 实际扩容大小,0表示已经达到最大,未成功扩容
|
||||
*/
|
||||
private int doIncrease(int increaseSize) {
|
||||
final int maxSize = config.getMaxSize();
|
||||
if (increaseSize + total > maxSize) {
|
||||
increaseSize = maxSize - total;
|
||||
}
|
||||
|
||||
try {
|
||||
Poolable<T> poolable;
|
||||
for (int i = 0; i < increaseSize; i++) {
|
||||
poolable = createPoolable();
|
||||
if(null != poolable){
|
||||
queue.put(poolable);
|
||||
}
|
||||
}
|
||||
total += increaseSize;
|
||||
} catch (final InterruptedException e) {
|
||||
throw new PoolException(e);
|
||||
}
|
||||
return increaseSize;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,9 +16,8 @@
|
||||
|
||||
package org.dromara.hutool.core.stream;
|
||||
|
||||
import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
@ -112,7 +111,7 @@ public class CollectorUtil {
|
||||
final Supplier<A> downstreamSupplier = downstream.supplier();
|
||||
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
|
||||
final BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
|
||||
final K key = Opt.ofNullable(t).map(classifier).orElse(null);
|
||||
final K key = Optional.ofNullable(t).map(classifier).orElse(null);
|
||||
final A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
|
||||
if (ArrayUtil.isArray(container) || Objects.nonNull(t)) {
|
||||
// 如果是数组类型,不需要判空,场景——分组后需要使用:java.util.unwrap.Collectors.counting 求null元素个数
|
||||
@ -288,7 +287,8 @@ public class CollectorUtil {
|
||||
final BinaryOperator<U> mergeFunction,
|
||||
final Supplier<M> mapSupplier) {
|
||||
final BiConsumer<M, T> accumulator
|
||||
= (map, element) -> map.put(Opt.ofNullable(element).map(keyMapper).get(), Opt.ofNullable(element).map(valueMapper).get());
|
||||
= (map, element) -> map.put(Optional.ofNullable(element).map(keyMapper).orElse(null),
|
||||
Optional.ofNullable(element).map(valueMapper).orElse(null));
|
||||
return new SimpleCollector<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
|
||||
}
|
||||
|
||||
@ -464,7 +464,7 @@ public class CollectorUtil {
|
||||
final Collector<? super T, A, R> downstream) {
|
||||
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
|
||||
return new SimpleCollector<>(downstream.supplier(),
|
||||
(r, t) -> Opt.of(t).filter(predicate).ifPresent(e -> downstreamAccumulator.accept(r, e)),
|
||||
(r, t) -> Optional.of(t).filter(predicate).ifPresent(e -> downstreamAccumulator.accept(r, e)),
|
||||
downstream.combiner(), downstream.finisher(),
|
||||
downstream.characteristics());
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ public class BeanTree<T, R extends Comparable<R>> {
|
||||
final Predicate<T> recursive = SerPredicate.multiOr(condition::test,
|
||||
e -> Opt.ofEmptyAble(childrenGetter.apply(e))
|
||||
.map(children -> EasyStream.of(children).filter(recursiveRef.get()).toList())
|
||||
.peek(children -> childrenSetter.accept(e, children))
|
||||
.ifPresent(children -> childrenSetter.accept(e, children))
|
||||
.filter(s -> !s.isEmpty()).isPresent());
|
||||
recursiveRef.set(recursive);
|
||||
return EasyStream.of(tree).filter(recursive).toList();
|
||||
@ -215,7 +215,7 @@ public class BeanTree<T, R extends Comparable<R>> {
|
||||
final AtomicReference<Consumer<T>> recursiveRef = new AtomicReference<>();
|
||||
final Consumer<T> recursive = SerConsumer.multi(action::accept,
|
||||
e -> Opt.ofEmptyAble(childrenGetter.apply(e))
|
||||
.peek(children -> EasyStream.of(children).forEach(recursiveRef.get())));
|
||||
.ifPresent(children -> EasyStream.of(children).forEach(recursiveRef.get())));
|
||||
recursiveRef.set(recursive);
|
||||
EasyStream.of(tree).forEach(recursive);
|
||||
return tree;
|
||||
|
@ -72,23 +72,23 @@ public class OptTest {
|
||||
public void peekTest() {
|
||||
final User user = new User();
|
||||
// 相当于ifPresent的链式调用
|
||||
Opt.ofNullable("hutool").peek(user::setUsername).peek(user::setNickname);
|
||||
Opt.ofNullable("hutool").ifPresent(user::setUsername).ifPresent(user::setNickname);
|
||||
Assertions.assertEquals("hutool", user.getNickname());
|
||||
Assertions.assertEquals("hutool", user.getUsername());
|
||||
|
||||
// 注意,传入的lambda中,对包裹内的元素执行赋值操作并不会影响到原来的元素
|
||||
final String name = Opt.ofNullable("hutool").peek(username -> username = "123").peek(username -> username = "456").get();
|
||||
final String name = Opt.ofNullable("hutool").ifPresent(username -> username = "123").ifPresent(username -> username = "456").get();
|
||||
Assertions.assertEquals("hutool", name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void peeksTest() {
|
||||
public void ifPresentsTest() {
|
||||
final User user = new User();
|
||||
// 相当于上面peek的动态参数调用,更加灵活,你可以像操作数组一样去动态设置中间的步骤,也可以使用这种方式去编写你的代码
|
||||
// 可以一行搞定
|
||||
Opt.ofNullable("hutool").peeks(user::setUsername, user::setNickname);
|
||||
Opt.ofNullable("hutool").ifPresents(user::setUsername, user::setNickname);
|
||||
// 也可以在适当的地方换行使得代码的可读性提高
|
||||
Opt.of(user).peeks(
|
||||
Opt.of(user).ifPresents(
|
||||
u -> Assertions.assertEquals("hutool", u.getNickname()),
|
||||
u -> Assertions.assertEquals("hutool", u.getUsername())
|
||||
);
|
||||
@ -97,14 +97,14 @@ public class OptTest {
|
||||
|
||||
// 注意,传入的lambda中,对包裹内的元素执行赋值操作并不会影响到原来的元素,这是java语言的特性。。。
|
||||
// 这也是为什么我们需要getter和setter而不直接给bean中的属性赋值中的其中一个原因
|
||||
final String name = Opt.ofNullable("hutool").peeks(
|
||||
final String name = Opt.ofNullable("hutool").ifPresents(
|
||||
username -> username = "123", username -> username = "456",
|
||||
n -> Assertions.assertEquals("hutool", n)).get();
|
||||
Assertions.assertEquals("hutool", name);
|
||||
|
||||
// 当然,以下情况不会抛出NPE,但也没什么意义
|
||||
Opt.ofNullable("hutool").peeks().peeks().peeks();
|
||||
Opt.ofNullable(null).peeks(i -> {
|
||||
Opt.ofNullable("hutool").ifPresents().ifPresents().ifPresents();
|
||||
Opt.ofNullable(null).ifPresents(i -> {
|
||||
});
|
||||
|
||||
}
|
||||
@ -254,7 +254,6 @@ public class OptTest {
|
||||
Assertions.assertEquals(i, 1);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"NumericOverflow", "divzero"})
|
||||
@Test
|
||||
@Disabled
|
||||
void testToEasyStream() {
|
||||
|
@ -56,8 +56,8 @@ public class PartitionObjectPoolTest {
|
||||
Assertions.assertEquals(4, pool.getTotal());
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
final Poolable<StringBuilder> obj = pool.borrowObject();
|
||||
obj.getRaw().append("hutool");
|
||||
final StringBuilder obj = pool.borrowObject();
|
||||
obj.append("hutool");
|
||||
}
|
||||
// 池1的2个+池2借出的20个,合计22个
|
||||
Assertions.assertEquals(22, pool.getTotal());
|
||||
@ -73,10 +73,10 @@ public class PartitionObjectPoolTest {
|
||||
// 初始4个对象
|
||||
Assertions.assertEquals(4, pool.getTotal());
|
||||
|
||||
final ArrayList<Poolable<StringBuilder>> borrowed = ListUtil.of();
|
||||
final ArrayList<StringBuilder> borrowed = ListUtil.of();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
final Poolable<StringBuilder> obj = pool.borrowObject();
|
||||
obj.getRaw().append("hutool");
|
||||
final StringBuilder obj = pool.borrowObject();
|
||||
obj.append("hutool");
|
||||
borrowed.add(obj);
|
||||
}
|
||||
// 池1的2个+池2借出的10个,合计12个
|
||||
@ -85,7 +85,7 @@ public class PartitionObjectPoolTest {
|
||||
Assertions.assertEquals(2, pool.getIdleCount());
|
||||
|
||||
// 全部归还
|
||||
for (final Poolable<StringBuilder> obj : borrowed) {
|
||||
for (final StringBuilder obj : borrowed) {
|
||||
pool.returnObject(obj);
|
||||
}
|
||||
|
||||
|
@ -98,12 +98,12 @@ public class PooledConnection extends ConnectionWrapper implements Poolable<Conn
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastBorrow() {
|
||||
public long getLastReturn() {
|
||||
return lastBorrow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastBorrow(final long lastBorrow) {
|
||||
this.lastBorrow = lastBorrow;
|
||||
public void setLastReturn(final long lastReturn) {
|
||||
this.lastBorrow = lastReturn;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user