首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 讀取 Level-1 行情 DBF 文件極致優化(三):字段解析與並行處理

     編輯:Java 綜合教學

Java 讀取 Level-1 行情 DBF 文件極致優化(三)

近期架構一個低延遲行情接入分發系統,需支持 Level-1、Level-2 等多源。Level-1 行情由行情小站定時更新 DBF 文件(上海 show2003.dbf、深圳 sjshq.dbf),目標是在文件更新完成後,以最短時間讀取入內存、轉換對象與數據類型。本系列共採用 6 種優化策略,前兩篇已介紹 4 項:

  1. 採用內存硬盤
  2. 採用 JNotify 通知替代輪詢
  3. 採用 NIO 讀取文件
  4. 減少內存重複分配與 GC

優化五:字段讀取優化

DBF 中價格字段帶 2-3 位小數,存儲為 Long/Int 而非 Float/Double 以避免精度丟失(如 1.23 存為 1230)。未優化流程需:讀取 byte[]→String→trim→Float→×1000→Long,涉及多次拷貝與對象創建,效率低下。

優化方案:在 DBFReader 中新增 get_long_efficiently_and_multiply_1000,單次掃描完成解析與乘法:

public long get_long_efficiently_and_multiply_1000(byte[] src, final int index) {
    long multiplicand = 3;
    long result = 0;
    Field field = getFields()[index];
    boolean in_decimal_part = false;
    boolean negative = false;
    int offset = field.getOffset();
    int length = field.getLength();
    int end = offset + length;
    for (int i = offset; i < end; i++) {
        byte ch = src[i];
        if (ch >= 48 && ch <= 57) { // 數字
            result *= 10;
            result += ch - 48;
            if (in_decimal_part) multiplicand--;
            if (multiplicand == 0) break;
            continue;
        }
        if (ch == 32) continue; // 空格
        if (ch == 46) { in_decimal_part = true; continue; } // 小數點
        if (ch == '-') { negative = true; }
        throw new NumberFormatException();
    }
    if (multiplicand == 3) result *= 1000;
    else if (multiplicand == 2) result *= 100;
    else if (multiplicand == 1) result *= 10;
    if (negative) result = 0 - result;
    return result;
}

整型字段同理優化為 get_long_efficiently。測試顯示,讀取耗時從 50-70ms 降至 15-20ms,為提升最大的單項優化。

DBFReader庫下載 DBFReader 庫下載

優化六:線程池並行處理

5000+ 行數據轉換天然適合多線程。傳統等分任務(如 5 線程各 1000 行)因 OS 時間片調度導致負載不均。採用「工作窃取」式動態分配:每線程每次申請 16 行,完成後再取,快線程多幹,慢線程少幹。協調靠 AtomicInteger (CAS) 無鎖實現:

class ReaderTask implements Runnable {
    // ... 構造器省略
    @Override public void run() {
        try {
            int length = recordList.size();
            final int step = 16;
            do {
                int endIndex = cursor.addAndGet(step);
                int startIndex = endIndex - step;
                for (int i = startIndex; i < endIndex && i < length; i++) {
                    byte[] row = recordList.get(i);
                    MarketRealtimeData data = new MarketRealtimeData();
                    data.setMarketType(Constants.MARKET_SH_STOCK);
                    data.setIdNum(reader.get_string_efficiently(row, 0));
                    data.setPreClosePrice(reader.get_long_efficiently_and_multiply_1000(row, 2));
                    // ... 其餘字段省略
                    if (collector != null) collector.collect(data);
                }
            } while (cursor.get() < length);
        } finally {
            if (countDownLatch != null) countDownLatch.countDown();
        }
    }
}

主流程:

private void readHangqingFile(String path, String name) throws Exception {
    DBFReader dbfreader = new DBFReader(new File(path + File.separator + name));
    List<byte[]> list = dbfreader.recordsWithOutDel_efficiently(cacheManager);
    AtomicInteger cursor = new AtomicInteger(0);
    CountDownLatch latch = new CountDownLatch(WORK_THREAD_COUNT);
    for (int i = 0; i < WORK_THREAD_COUNT - 1; i++) {
        globalExecutor.execute(new ReaderTask(collector, dbfreader, list, cursor, latch));
    }
    new ReaderTask(collector, dbfreader, list, cursor, latch).run(); // 主線程也參與
    latch.await();
}

4 線程並行下,處理時間從 15-20ms 縮短至 4-7ms。綜合 6 項優化,端到端耗時從 300ms+ 降至 5-10ms。後續可從減少對象創建、控制 GC 執行時機進一步穩定延遲。

原文地址:https://www.cnblogs.com/Binhua-Liu/p/5616761.html

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved