public void run() {
   try {
     Process(this.userId); // process each user
   } catch (Exception e) {
     e.printStackTrace();
     Clogging.Warn("Process::run exception userid:" + this.userId);
   } finally {
     this.userId = null;
   }
 }
  /**
   * process each person
   *
   * @param userId
   */
  private void Process(int userId) {
    Long startTime = System.currentTimeMillis();

    Strategy strategy =
        new GeneralStrategy(); // use general strategy for total users, including recommendation of
                               // content
    List<Category> categoryList = strategy.getStrategy(userId);

    List<DataBuilder> builderList =
        new ArrayList<DataBuilder>(); // builderList for creating data by different type
    for (Category each : categoryList) {
      DataBuilder builder = BuilderFactory.createBuilder(each.getType());
      builderList.add(builder);
    }

    if (categoryList.size() != builderList.size()) {
      Clogging.Error("[Process] size of categoryList is not as same as size of builderList!!");
      return;
    }

    BlockFetcher blockFetcher =
        new SgBlockFetcher(); // fetch block list from socialgraph block table
    List<Long> blockList =
        blockFetcher.getBlockList(userId); // fetch block list from specific fetcher
    Set<Long> filterSet = new HashSet<Long>();
    filterSet.addAll(blockList);

    Items.Builder result = Items.newBuilder();
    int typeSize = 0; // number of each type, changing according to size of pre-type

    for (int i = 0; i < categoryList.size(); ++i) {
      typeSize += categoryList.get(i).getNum(); // get size of current type

      if (null == builderList.get(i)
          || categoryList.get(i).getType() != builderList.get(i).getBuilderType()) {
        continue;
      }

      int realTypeSize = 0;
      List<DataItem> dataList = builderList.get(i).getData(userId); // create data
      for (DataItem it : dataList) { // combine data of the type
        if (filterSet.contains(it.getId())) {
          continue;
        } else {
          if (realTypeSize < typeSize) {
            filterSet.add(it.getId());
            result.addItems(it.getItem());
            ++realTypeSize;
          } else {
            break;
          }
        }
      }
      typeSize = typeSize - realTypeSize; // left remnant to next type
      dataList = null; // clean
    }

    byte[] resultData = result.build().toByteArray();
    boolean insert = false;
    if (null != resultData && resultData.length != 0) {
      insert = BusinessCacheAdapter.getInstance().set(PUK, userId, resultData);
    }

    Long endTime = System.currentTimeMillis();
    if (insert) {
      Clogging.Debug(
          "userId:"
              + userId
              + " Success resultData size:"
              + resultData.length
              + " cost_time:"
              + (endTime - startTime)
              + "ms");
    } else {
      Clogging.Debug(
          "userId:"
              + userId
              + " Fail resultData size:"
              + resultData.length
              + " cost_time:"
              + (endTime - startTime)
              + "ms");
    }

    result = null; // clean
    resultData = null;
    strategy = null;
    categoryList = null;
    builderList = null;
    blockFetcher = null;
    filterSet = null;
    blockList = null;
  }