mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
ec5fcaa76b
commit
77e4600d44
@ -19,6 +19,7 @@ package org.dromara.hutool.core.thread;
|
||||
import org.dromara.hutool.core.util.RuntimeUtil;
|
||||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletionService;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@ -203,9 +204,9 @@ public class ThreadUtil {
|
||||
* @since 5.8.0
|
||||
*/
|
||||
public static ThreadPoolExecutor newFixedExecutor(final int nThreads,
|
||||
final int maximumQueueSize,
|
||||
final String threadNamePrefix,
|
||||
final RejectedExecutionHandler handler) {
|
||||
final int maximumQueueSize,
|
||||
final String threadNamePrefix,
|
||||
final RejectedExecutionHandler handler) {
|
||||
return ExecutorBuilder.of()
|
||||
.setCorePoolSize(nThreads).setMaxPoolSize(nThreads)
|
||||
.setWorkQueue(new LinkedBlockingQueue<>(maximumQueueSize))
|
||||
@ -429,6 +430,8 @@ public class ThreadUtil {
|
||||
return t;
|
||||
}
|
||||
|
||||
// region ----- sleep
|
||||
|
||||
/**
|
||||
* 挂起当前线程
|
||||
*
|
||||
@ -458,6 +461,20 @@ public class ThreadUtil {
|
||||
return sleep(millis.longValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前线程
|
||||
*
|
||||
* @param duration 挂起的时长
|
||||
* @return 被中断返回false,否则true
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static boolean sleep(final Duration duration) {
|
||||
if (duration == null) {
|
||||
return true;
|
||||
}
|
||||
return sleep(duration.toMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前线程
|
||||
*
|
||||
@ -491,6 +508,20 @@ public class ThreadUtil {
|
||||
return safeSleep(millis.longValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前线程
|
||||
*
|
||||
* @param duration 挂起的时长
|
||||
* @return 被中断返回false,否则true
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static boolean safeSleep(final Duration duration) {
|
||||
if (duration == null) {
|
||||
return true;
|
||||
}
|
||||
return safeSleep(duration.toMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 考虑{@link Thread#sleep(long)}方法有可能时间不足给定毫秒数,此方法保证sleep时间不小于给定的毫秒数
|
||||
*
|
||||
@ -513,6 +544,7 @@ public class ThreadUtil {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* @return 获得堆栈列表
|
||||
|
@ -25,6 +25,15 @@ package org.dromara.hutool.core.thread.ratelimiter;
|
||||
*/
|
||||
public interface RateLimiter {
|
||||
|
||||
/**
|
||||
* 尝试获取许可,非阻塞方法
|
||||
*
|
||||
* @return {@code true}表示成功获取,{@code false}表示无足够的许可可获取,此时需要等待给定的时间
|
||||
*/
|
||||
default boolean tryAcquire() {
|
||||
return tryAcquire(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试获取许可,非阻塞方法
|
||||
*
|
||||
@ -32,4 +41,18 @@ public interface RateLimiter {
|
||||
* @return {@code true}表示成功获取,{@code false}表示无足够的许可可获取,此时需要等待给定的时间
|
||||
*/
|
||||
boolean tryAcquire(int permits);
|
||||
|
||||
/**
|
||||
* 获取许可,阻塞方法,如果没有足够的许可,则阻塞等待
|
||||
*/
|
||||
default void acquire() {
|
||||
acquire(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取许可,阻塞方法,如果没有足够的许可,则阻塞等待
|
||||
*
|
||||
* @param permits 需要的许可数
|
||||
*/
|
||||
void acquire(int permits);
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package org.dromara.hutool.core.thread.ratelimiter;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* 限流通用配置
|
||||
*
|
||||
@ -27,23 +29,23 @@ public class RateLimiterConfig {
|
||||
/**
|
||||
* 创建限流配置
|
||||
*
|
||||
* @param timeoutDuration 超时时间,即超过这个时间没有获取到许可,则返回false
|
||||
* @param timeout 超时时间,即超过这个时间没有获取到许可,则返回false
|
||||
* @param limitRefreshPeriod 限制刷新周期,即每多少时间刷新一次
|
||||
* @param limitForPeriod 个周期的许可数
|
||||
* @return RateLimiterConfig
|
||||
*/
|
||||
public static RateLimiterConfig of(final long timeoutDuration, final long limitRefreshPeriod, final int limitForPeriod) {
|
||||
return new RateLimiterConfig(timeoutDuration, limitRefreshPeriod, limitForPeriod);
|
||||
public static RateLimiterConfig of(final Duration timeout, final Duration limitRefreshPeriod, final int limitForPeriod) {
|
||||
return new RateLimiterConfig(timeout, limitRefreshPeriod, limitForPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
* 超时时间,即超过这个时间没有获取到许可,则返回false,单位毫秒
|
||||
* 超时时间,即超过这个时间没有获取到许可,则返回false
|
||||
*/
|
||||
private final long timeoutDuration;
|
||||
private final Duration timeout;
|
||||
/**
|
||||
* 限制刷新周期,即每多少时间刷新一次,单位毫秒
|
||||
* 限制刷新周期,即每多少时间刷新一次
|
||||
*/
|
||||
private final long limitRefreshPeriod;
|
||||
private final Duration limitRefreshPeriod;
|
||||
/**
|
||||
* 每个周期的许可数
|
||||
*/
|
||||
@ -52,12 +54,12 @@ public class RateLimiterConfig {
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param timeoutDuration 超时时间,即超过这个时间没有获取到许可,则返回false
|
||||
* @param timeout 超时时间,即超过这个时间没有获取到许可,则返回false
|
||||
* @param limitRefreshPeriod 限制刷新周期,即每多少时间刷新一次
|
||||
* @param limitForPeriod 个周期的许可数
|
||||
*/
|
||||
public RateLimiterConfig(final long timeoutDuration, final long limitRefreshPeriod, final int limitForPeriod) {
|
||||
this.timeoutDuration = timeoutDuration;
|
||||
public RateLimiterConfig(final Duration timeout, final Duration limitRefreshPeriod, final int limitForPeriod) {
|
||||
this.timeout = timeout;
|
||||
this.limitRefreshPeriod = limitRefreshPeriod;
|
||||
this.limitForPeriod = limitForPeriod;
|
||||
}
|
||||
@ -67,8 +69,8 @@ public class RateLimiterConfig {
|
||||
*
|
||||
* @return 超时时间,单位毫秒
|
||||
*/
|
||||
public long getTimeoutDuration() {
|
||||
return timeoutDuration;
|
||||
public Duration getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,7 +78,7 @@ public class RateLimiterConfig {
|
||||
*
|
||||
* @return 限制刷新周期,单位毫秒
|
||||
*/
|
||||
public long getLimitRefreshPeriod() {
|
||||
public Duration getLimitRefreshPeriod() {
|
||||
return limitRefreshPeriod;
|
||||
}
|
||||
|
||||
|
@ -31,39 +31,39 @@ import java.util.concurrent.*;
|
||||
*/
|
||||
public class SemaphoreRateLimiter implements RateLimiter {
|
||||
|
||||
private final RateLimiterConfig rateLimiterConfig;
|
||||
private final RateLimiterConfig config;
|
||||
private final ScheduledExecutorService scheduler;
|
||||
private final Semaphore semaphore;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param rateLimiterConfig 限流配置
|
||||
* @param config 限流配置
|
||||
*/
|
||||
public SemaphoreRateLimiter(final RateLimiterConfig rateLimiterConfig) {
|
||||
this(rateLimiterConfig, null);
|
||||
public SemaphoreRateLimiter(final RateLimiterConfig config) {
|
||||
this(config, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param rateLimiterConfig 限流配置
|
||||
* @param config 限流配置
|
||||
* @param semaphore {@link Semaphore}
|
||||
*/
|
||||
public SemaphoreRateLimiter(final RateLimiterConfig rateLimiterConfig, final Semaphore semaphore) {
|
||||
this(rateLimiterConfig, semaphore, null);
|
||||
public SemaphoreRateLimiter(final RateLimiterConfig config, final Semaphore semaphore) {
|
||||
this(config, semaphore, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param rateLimiterConfig 限流配置
|
||||
* @param config 限流配置
|
||||
* @param semaphore {@link Semaphore}
|
||||
* @param scheduler 定时器
|
||||
*/
|
||||
public SemaphoreRateLimiter(final RateLimiterConfig rateLimiterConfig, final Semaphore semaphore, final ScheduledExecutorService scheduler) {
|
||||
this.rateLimiterConfig = Assert.notNull(rateLimiterConfig);
|
||||
this.semaphore = Opt.ofNullable(semaphore).orElseGet(() -> new Semaphore(rateLimiterConfig.getLimitForPeriod()));
|
||||
public SemaphoreRateLimiter(final RateLimiterConfig config, final Semaphore semaphore, final ScheduledExecutorService scheduler) {
|
||||
this.config = Assert.notNull(config);
|
||||
this.semaphore = Opt.ofNullable(semaphore).orElseGet(() -> new Semaphore(config.getLimitForPeriod()));
|
||||
this.scheduler = Opt.ofNullable(scheduler).orElseGet(this::configureScheduler);
|
||||
//启动定时器
|
||||
scheduleLimitRefresh();
|
||||
@ -74,6 +74,11 @@ public class SemaphoreRateLimiter implements RateLimiter {
|
||||
return semaphore.tryAcquire(permits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acquire(final int permits) {
|
||||
semaphore.acquireUninterruptibly(permits);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新限制,填满许可数为{@link RateLimiterConfig#getLimitForPeriod()}<br>
|
||||
* 用户可手动调用此方法填满许可
|
||||
@ -81,7 +86,7 @@ public class SemaphoreRateLimiter implements RateLimiter {
|
||||
* @see RateLimiterConfig#getLimitForPeriod()
|
||||
*/
|
||||
public void refreshLimit() {
|
||||
semaphore.release(this.rateLimiterConfig.getLimitForPeriod() - semaphore.availablePermits());
|
||||
semaphore.release(this.config.getLimitForPeriod() - semaphore.availablePermits());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,12 +103,12 @@ public class SemaphoreRateLimiter implements RateLimiter {
|
||||
* 启动定时器
|
||||
*/
|
||||
private void scheduleLimitRefresh() {
|
||||
final long limitRefreshPeriod = this.rateLimiterConfig.getLimitRefreshPeriod();
|
||||
final long limitRefreshPeriod = this.config.getLimitRefreshPeriod().toNanos();
|
||||
scheduler.scheduleAtFixedRate(
|
||||
this::refreshLimit,
|
||||
limitRefreshPeriod,
|
||||
limitRefreshPeriod,
|
||||
TimeUnit.MILLISECONDS
|
||||
TimeUnit.NANOSECONDS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,13 @@ import org.dromara.hutool.core.thread.ThreadUtil;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class SemaphoreRateLimiterTest {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
final RateLimiterConfig rateLimiterConfig = RateLimiterConfig.of(5000, 300, 5);
|
||||
final RateLimiterConfig rateLimiterConfig = RateLimiterConfig.of(Duration.ofSeconds(5), Duration.ofMillis(300), 5);
|
||||
final RateLimiter rateLimiter = new SemaphoreRateLimiter(rateLimiterConfig);
|
||||
|
||||
final boolean b = rateLimiter.tryAcquire(5);
|
||||
@ -16,7 +18,9 @@ public class SemaphoreRateLimiterTest {
|
||||
// 超过数量
|
||||
final boolean b1 = rateLimiter.tryAcquire(1);
|
||||
Assertions.assertFalse(b1);
|
||||
|
||||
ThreadUtil.sleep(310);
|
||||
|
||||
// 填充新的许可
|
||||
final boolean b2 = rateLimiter.tryAcquire(5);
|
||||
Assertions.assertTrue(b2);
|
||||
|
Loading…
x
Reference in New Issue
Block a user