@Getter
@AllArgsConstructor
public enum InsertQueueEnum {
A(30000, 10, TimeUnit.SECONDS, 2, 1000),
;
private final int capacity;//佇列長度
private final int time;//最長阻塞時間
private final TimeUnit timeUnit;//最長阻塞時間單位
private final int threads;//消費執行緒數
private final int consumptionBatchNum;//單次消費數量
}
該方法在空閒時不會造成空轉
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class InsertQueue {
//單例插入佇列
//列舉型別為所有佇列型別
private static final Map<InsertQueueEnum, ArrayBlockingQueue<Object>> TYPE_QUEUE_MAP = new EnumMap<>(InsertQueueEnum.class);
static {
for (InsertQueueEnum value : InsertQueueEnum.values()) {
log.info("[" + InsertQueue.class.getSimpleName() + "]" + value + "佇列長度" + value.getCapacity());
TYPE_QUEUE_MAP.put(value, new ArrayBlockingQueue<>(value.getCapacity()));
}
}
public static boolean pushObject(InsertQueueEnum type, Object obj) {
try {
TYPE_QUEUE_MAP.get(type).put(obj);
return true;
} catch (Exception e) {
return false;
}
}
public static <T> List<T> popObject(InsertQueueEnum type, int batchSize, long maxWaitTime, TimeUnit unit, Class<T> clazz) {
//拿到batchSize個元素或超過maxWaitTime才返回,返回容器不會為空
ArrayBlockingQueue<?> queue = TYPE_QUEUE_MAP.get(type);
try {
List<T> objects = new ArrayList<>();
Object head = queue.take();//阻塞
objects.add(clazz.cast(head));
long startMillis = System.currentTimeMillis();
long exitMillis = startMillis + unit.toMillis(maxWaitTime);
for (int i = 1; i < batchSize && System.currentTimeMillis() <= exitMillis; i++) {
head = queue.poll(maxWaitTime, unit);
if (head == null) {
break;
}
objects.add(clazz.cast(head));
}
return objects;
} catch (Exception e) {
log.error("[" + InsertQueue.class.getSimpleName() + "]" + type + "佇列獲取元素出錯", e);
return Collections.emptyList();
}
}
public static int getQueueSize(InsertQueueEnum type) {
return TYPE_QUEUE_MAP.get(type).size();
}
}