一个Java基于阻塞的定时消费内存队列
@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();
}
}