一個Java基於阻塞的定時消費記憶體佇列

用户名还没想好發表於2024-05-16

@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();
  }

}

相關文章