content: package com.genersoft.iot.vmp.jt1078.codec.decode;
  
  import com.genersoft.iot.vmp.jt1078.proc.Header;
  import io.netty.buffer.*;
  import lombok.extern.slf4j.Slf4j;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import java.util.*;
  import java.util.concurrent.ConcurrentHashMap;
  
  @Slf4j
  public enum MultiPacketManager {
      INSTANCE;
      // 用与消息的缓存
      private final Map<String, CompositeByteBuf> packetMap = new ConcurrentHashMap<>();
      private final Map<String, Long> packetTimeMap = new ConcurrentHashMap<>();
  
      MultiPacketManager() {
          startLister();
      }
  
      /**
       * 增加待合并的分包，如果分包接受完毕会返回完整的数据包
       */
      public ByteBuf add(Header header, Integer count, ByteBuf byteBuf) {
          String key = header.getMsgId() + "/" + header.getPhoneNumber();
          CompositeByteBuf compositeBuf = packetMap.computeIfAbsent(key, k -> new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, false, count));
  //        compositeBuf.addComponent(true, byteBuf.readSlice(byteBuf.readableBytes()));
          compositeBuf.addComponent(true, byteBuf);
          packetTimeMap.put(key, System.currentTimeMillis());
          if (count == compositeBuf.numComponents()) {
              packetMap.remove(key);
              packetTimeMap.remove(key);
              compositeBuf.retain();
              return compositeBuf;
          }
          return null;
      }
  
      private void startLister(){
          Timer timer = new Timer();
          timer.schedule(new TimerTask() {
              @Override
              public void run() {
                  long expireTime = System.currentTimeMillis() - 20 * 1000;
                  if (!packetTimeMap.isEmpty()) {
                      for (String key : packetTimeMap.keySet()) {
                          if (packetTimeMap.get(key) < expireTime) {
                              log.info("分包消息超时 key: {}", key);
                              packetTimeMap.remove(key);
                              packetMap.remove(key);
                          }
                      }
                  }
              }
          }, 2000L, 2000L);
      }
  }
  