|
@@ -1,12 +1,12 @@
|
|
|
package com.chelvc.framework.common.util;
|
|
|
|
|
|
import java.util.Collection;
|
|
|
+import java.util.Collections;
|
|
|
import java.util.List;
|
|
|
import java.util.concurrent.ArrayBlockingQueue;
|
|
|
import java.util.concurrent.BlockingQueue;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.function.Consumer;
|
|
|
-import java.util.function.Supplier;
|
|
|
import java.util.stream.Collectors;
|
|
|
import java.util.stream.IntStream;
|
|
|
|
|
@@ -35,6 +35,7 @@ public final class ThreadUtils {
|
|
|
try {
|
|
|
Thread.sleep(millis);
|
|
|
} catch (InterruptedException ignored) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
return false;
|
|
|
}
|
|
|
return true;
|
|
@@ -79,6 +80,8 @@ public final class ThreadUtils {
|
|
|
try {
|
|
|
thread.join();
|
|
|
} catch (InterruptedException ignored) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -93,34 +96,32 @@ public final class ThreadUtils {
|
|
|
try {
|
|
|
thread.join();
|
|
|
} catch (InterruptedException ignored) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 异步消费消息
|
|
|
+ * 中断线程
|
|
|
*
|
|
|
- * @param queue 阻塞队列
|
|
|
- * @param consumer 消息消费者
|
|
|
- * @param <T> 消息类型
|
|
|
- * @return 消费线程列表
|
|
|
+ * @param threads 线程对象数组
|
|
|
*/
|
|
|
- public static <T> List<Thread> consume(@NonNull BlockingQueue<T> queue, @NonNull Consumer<T> consumer) {
|
|
|
- return consume(queue, consumer, 3);
|
|
|
+ public static void interrupt(@NonNull Thread... threads) {
|
|
|
+ for (Thread thread : threads) {
|
|
|
+ thread.interrupt();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 异步消费消息
|
|
|
+ * 中断线程
|
|
|
*
|
|
|
- * @param queue 阻塞队列
|
|
|
- * @param consumer 消息消费者
|
|
|
- * @param concurrency 并发数量
|
|
|
- * @param <T> 消息类型
|
|
|
- * @return 消费线程列表
|
|
|
+ * @param threads 线程对象集合
|
|
|
*/
|
|
|
- public static <T> List<Thread> consume(@NonNull BlockingQueue<T> queue,
|
|
|
- @NonNull Consumer<T> consumer, int concurrency) {
|
|
|
- return consume(queue, consumer, () -> true, concurrency);
|
|
|
+ public static void interrupt(@NonNull Collection<Thread> threads) {
|
|
|
+ for (Thread thread : threads) {
|
|
|
+ thread.interrupt();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -128,14 +129,11 @@ public final class ThreadUtils {
|
|
|
*
|
|
|
* @param queue 阻塞队列
|
|
|
* @param consumer 消息消费者
|
|
|
- * @param running 消费线程运行开关
|
|
|
* @param <T> 消息类型
|
|
|
* @return 消费线程列表
|
|
|
*/
|
|
|
- public static <T> List<Thread> consume(@NonNull BlockingQueue<T> queue,
|
|
|
- @NonNull Consumer<T> consumer,
|
|
|
- @NonNull Supplier<Boolean> running) {
|
|
|
- return consume(queue, consumer, running, 3);
|
|
|
+ public static <T> List<Thread> consume(@NonNull BlockingQueue<T> queue, @NonNull Consumer<T> consumer) {
|
|
|
+ return consume(queue, consumer, 3);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -143,21 +141,23 @@ public final class ThreadUtils {
|
|
|
*
|
|
|
* @param queue 阻塞队列
|
|
|
* @param consumer 消息消费者
|
|
|
- * @param running 消费线程运行开关
|
|
|
* @param concurrency 并发数量
|
|
|
* @param <T> 消息类型
|
|
|
* @return 消费线程列表
|
|
|
*/
|
|
|
public static <T> List<Thread> consume(@NonNull BlockingQueue<T> queue, @NonNull Consumer<T> consumer,
|
|
|
- @NonNull Supplier<Boolean> running, int concurrency) {
|
|
|
+ int concurrency) {
|
|
|
return IntStream.range(0, concurrency).mapToObj(i -> run(() -> {
|
|
|
- while (Boolean.TRUE.equals(running.get()) && !Thread.interrupted()) {
|
|
|
- T message;
|
|
|
+ while (!Thread.currentThread().isInterrupted()) {
|
|
|
+ // 从队列中获取消息
|
|
|
+ T message = null;
|
|
|
try {
|
|
|
message = queue.poll(1, TimeUnit.SECONDS);
|
|
|
} catch (InterruptedException ignored) {
|
|
|
- break;
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
}
|
|
|
+
|
|
|
+ // 消费消息
|
|
|
if (message != null) {
|
|
|
try {
|
|
|
consumer.accept(message);
|
|
@@ -174,38 +174,43 @@ public final class ThreadUtils {
|
|
|
*
|
|
|
* @param queue 阻塞队列
|
|
|
* @param consumer 消息消费者
|
|
|
- * @param running 消费线程运行开关
|
|
|
* @param concurrency 并发数量
|
|
|
* @param batchSize 批处理数量
|
|
|
* @param <T> 消息类型
|
|
|
* @return 消费线程列表
|
|
|
*/
|
|
|
public static <T> List<Thread> consume(@NonNull BlockingQueue<T> queue, @NonNull Consumer<List<T>> consumer,
|
|
|
- @NonNull Supplier<Boolean> running, int concurrency, int batchSize) {
|
|
|
+ int concurrency, int batchSize) {
|
|
|
return IntStream.range(0, concurrency).mapToObj(i -> run(() -> {
|
|
|
List<T> buffer = Lists.newArrayListWithCapacity(batchSize);
|
|
|
- while (Boolean.TRUE.equals(running.get()) && !Thread.interrupted()) {
|
|
|
- T message;
|
|
|
+ List<T> unmodifiable = Collections.unmodifiableList(buffer);
|
|
|
+ while (!Thread.currentThread().isInterrupted()) {
|
|
|
+ // 从队列中获取消息
|
|
|
+ T message = null;
|
|
|
try {
|
|
|
- message = queue.poll(1, TimeUnit.SECONDS);
|
|
|
+ message = queue.poll(3, TimeUnit.SECONDS);
|
|
|
} catch (InterruptedException ignored) {
|
|
|
- break;
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
}
|
|
|
+
|
|
|
+ // 将消息加入缓冲区
|
|
|
if (message != null) {
|
|
|
buffer.add(message);
|
|
|
- if (buffer.size() % batchSize == 0) {
|
|
|
- try {
|
|
|
- consumer.accept(buffer);
|
|
|
- } catch (Exception e) {
|
|
|
- log.error(e.getMessage(), e);
|
|
|
- } finally {
|
|
|
- buffer.clear();
|
|
|
- }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果获取消息超时或缓冲区消息数量达到batchSize则执行消费
|
|
|
+ if (buffer.size() > 0 && (message == null || buffer.size() % batchSize == 0)) {
|
|
|
+ try {
|
|
|
+ consumer.accept(unmodifiable);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ } finally {
|
|
|
+ buffer.clear();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (ObjectUtils.notEmpty(buffer)) {
|
|
|
- consumer.accept(buffer);
|
|
|
+ consumer.accept(unmodifiable);
|
|
|
}
|
|
|
})).collect(Collectors.toList());
|
|
|
}
|
|
@@ -218,19 +223,7 @@ public final class ThreadUtils {
|
|
|
* @return 消息队列
|
|
|
*/
|
|
|
public static <T> BlockingQueue<T> queue(@NonNull Consumer<T> consumer) {
|
|
|
- return queue(consumer, () -> true);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 异步消费消息
|
|
|
- *
|
|
|
- * @param consumer 消息消费者
|
|
|
- * @param running 消费线程运行开关
|
|
|
- * @param <T> 消息类型
|
|
|
- * @return 消息队列
|
|
|
- */
|
|
|
- public static <T> BlockingQueue<T> queue(@NonNull Consumer<T> consumer, @NonNull Supplier<Boolean> running) {
|
|
|
- return queue(1000, consumer, running);
|
|
|
+ return queue(1000, consumer);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -242,21 +235,7 @@ public final class ThreadUtils {
|
|
|
* @return 消息队列
|
|
|
*/
|
|
|
public static <T> BlockingQueue<T> queue(int capacity, @NonNull Consumer<T> consumer) {
|
|
|
- return queue(capacity, consumer, () -> true);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 异步消费消息
|
|
|
- *
|
|
|
- * @param capacity 队列大小
|
|
|
- * @param consumer 消息消费者
|
|
|
- * @param running 消费线程运行开关
|
|
|
- * @param <T> 消息类型
|
|
|
- * @return 消息队列
|
|
|
- */
|
|
|
- public static <T> BlockingQueue<T> queue(int capacity, @NonNull Consumer<T> consumer,
|
|
|
- @NonNull Supplier<Boolean> running) {
|
|
|
- return queue(capacity, consumer, running, 3);
|
|
|
+ return queue(capacity, consumer, 3);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -268,21 +247,7 @@ public final class ThreadUtils {
|
|
|
* @return 消息队列
|
|
|
*/
|
|
|
public static <T> BlockingQueue<T> queue(@NonNull Consumer<T> consumer, int concurrency) {
|
|
|
- return queue(consumer, () -> true, concurrency);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 异步消费消息
|
|
|
- *
|
|
|
- * @param consumer 消息消费者
|
|
|
- * @param running 消费线程运行开关
|
|
|
- * @param concurrency 并发数量
|
|
|
- * @param <T> 消息类型
|
|
|
- * @return 消息队列
|
|
|
- */
|
|
|
- public static <T> BlockingQueue<T> queue(@NonNull Consumer<T> consumer, @NonNull Supplier<Boolean> running,
|
|
|
- int concurrency) {
|
|
|
- return queue(1000, consumer, running, concurrency);
|
|
|
+ return queue(1000, consumer, concurrency);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -295,24 +260,22 @@ public final class ThreadUtils {
|
|
|
* @return 消息队列
|
|
|
*/
|
|
|
public static <T> BlockingQueue<T> queue(int capacity, @NonNull Consumer<T> consumer, int concurrency) {
|
|
|
- return queue(capacity, consumer, () -> true, concurrency);
|
|
|
+ BlockingQueue<T> queue = new ArrayBlockingQueue<>(Math.max(capacity, 1));
|
|
|
+ consume(queue, consumer, concurrency);
|
|
|
+ return queue;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 异步消费消息
|
|
|
*
|
|
|
- * @param capacity 队列大小
|
|
|
* @param consumer 消息消费者
|
|
|
- * @param running 消费线程运行开关
|
|
|
* @param concurrency 并发数量
|
|
|
+ * @param batchSize 批处理数量
|
|
|
* @param <T> 消息类型
|
|
|
* @return 消息队列
|
|
|
*/
|
|
|
- public static <T> BlockingQueue<T> queue(int capacity, @NonNull Consumer<T> consumer,
|
|
|
- @NonNull Supplier<Boolean> running, int concurrency) {
|
|
|
- BlockingQueue<T> queue = new ArrayBlockingQueue<>(Math.max(capacity, 1));
|
|
|
- consume(queue, consumer, running, concurrency);
|
|
|
- return queue;
|
|
|
+ public static <T> BlockingQueue<T> queue(@NonNull Consumer<List<T>> consumer, int concurrency, int batchSize) {
|
|
|
+ return queue(1000, consumer, concurrency, batchSize);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -320,16 +283,15 @@ public final class ThreadUtils {
|
|
|
*
|
|
|
* @param capacity 队列大小
|
|
|
* @param consumer 消息消费者
|
|
|
- * @param running 消费线程运行开关
|
|
|
* @param concurrency 并发数量
|
|
|
* @param batchSize 批处理数量
|
|
|
* @param <T> 消息类型
|
|
|
* @return 消息队列
|
|
|
*/
|
|
|
- public static <T> BlockingQueue<T> queue(int capacity, @NonNull Consumer<List<T>> consumer,
|
|
|
- @NonNull Supplier<Boolean> running, int concurrency, int batchSize) {
|
|
|
+ public static <T> BlockingQueue<T> queue(int capacity, @NonNull Consumer<List<T>> consumer, int concurrency,
|
|
|
+ int batchSize) {
|
|
|
BlockingQueue<T> queue = new ArrayBlockingQueue<>(Math.max(capacity, 1));
|
|
|
- consume(queue, consumer, running, concurrency, batchSize);
|
|
|
+ consume(queue, consumer, concurrency, batchSize);
|
|
|
return queue;
|
|
|
}
|
|
|
}
|