模擬實現mapreduce中環形緩衝區的讀寫過程
原型:
在mapreduce中,map task呼叫map處理邏輯將處理後的key和value利用outputcollector.collect()放入一個環形緩衝區中,那麼這個緩衝區是有一定大小的,那麼如果放入的內容很多很多的時候怎麼辦呢?其實hadoop裡面有這麼個機制,在緩衝區達到某一個值或者比率的時候,比如80%,那麼hadoop會利用Spiller.spill()將這個80%的資料讀出來按照HashPartitioner.getPartitioner()來進行分割槽並按照key進行快速排序,然後kv鍵值對會繼續向緩衝區中存放,形成一個環形儲存邏輯,只要達到80%就將這塊取出來,那麼緩衝區就會一直可用。
模擬實現:
定義了一個容量為100的字串陣列來模擬環形緩衝區。另外還定義了一個size用來決定原型中比率,預設值給的80.start用來記錄這個80內容的起始位置,一個布林型別的引數為true時意味著緩衝區中已經超過80,需要開始進行Spiller.spill()。
程式主要是兩個程式,第一個程式是不斷地將原始檔按行讀取,存入陣列中,當資料達到80的時候,將布林型別標記置為true,並設定起始位置,不需要考慮其他情況,當達到100的時候,會繼續往陣列中寫入資料,從0開始,不斷迴圈,知道檔案讀取完畢。
第二個程式會不斷去驗證標記位的值,如果為true,就會獲得當前起始位置,將標記位置為false,然後遍歷這80的資料,存入到某個編號檔案中,讀取完畢後會再次去嗅探標記位。
程式碼實現:
package com.season.spill;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class FileJobSubmitter {
public static final String FILE_READ ="F:\\io\\BufferInput\\season.txt";
public static String[] CIRCLE_BUFFER = new String[100];
public static int BUFFER_SIZE = 80;
public static int BUFFER_START = 0;
public static int BUFFER_COUNTS = 0;
public static boolean READ_FLAG = false;
public static int FILE_ID = 1000;
public static void main(String[] args) {
ReadFileToCircleBuffer rf = new ReadFileToCircleBuffer();
Thread rfThread = new Thread(rf);
WriteFileFromBuffer wf = new WriteFileFromBuffer();
Thread wfThread = new Thread(wf);
rfThread.start();
wfThread.start();
}
static class ReadFileToCircleBuffer implements Runnable {
@Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(FILE_READ))));
String lenTxt = null;
int i = 0 ;
while((lenTxt = br.readLine()) != null ){
CIRCLE_BUFFER[i] = lenTxt;
BUFFER_COUNTS++;
if(BUFFER_COUNTS == 80){
BUFFER_START = i < 79 ? 20 + i : i-79 ;
READ_FLAG = true ;
BUFFER_COUNTS = 0 ;
}
System.out.println("內容:"+lenTxt+" flag="+ READ_FLAG + " start="+ BUFFER_START+" 總數=" + BUFFER_COUNTS+" i = "+ i);
i = i==99?0:i+1;
Thread.sleep(1000);
}
BUFFER_START = i < BUFFER_COUNTS -1 ? 100 - BUFFER_COUNTS + i : i- BUFFER_COUNTS + 1 ;
READ_FLAG = true ;
BUFFER_SIZE = BUFFER_COUNTS;
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
static class WriteFileFromBuffer implements Runnable {
@Override
public void run() {
while (true) {
try {
if (READ_FLAG) {
READ_FLAG = false;
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("F:\\io\\BufferOutput\\part-" + FILE_ID + "size80.txt"))));
// 將起點開始的80個記錄存入檔案中
int start = BUFFER_START;
for (int i = 0; i < BUFFER_SIZE; i++) {
System.out.println( "*******存入:"+CIRCLE_BUFFER[start]);
String temp = CIRCLE_BUFFER[start];
bw.write(temp);
bw.newLine();
Thread.sleep(500);
start = start==99?0:start+1;
}
bw.close();
FILE_ID++;
}
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
總結:
其中有些輸出是為了檢視當前的進度來驗證程式的準確性。經過這次小小的練習,收穫頗豐,又將一些很少用到的基本知識複習了一般,不乏有長時間不用忘記的,其實,應該多拿出一些時間來實現某些簡單的小程式鞏固自己的基礎知識,拓實自己。
相關文章
- Duilib的雙緩衝實現,附帶GDI、WTL的雙緩衝實現UI
- MySQL中讀頁緩衝區buffer poolMySql
- 緩衝區溢位實驗
- C 標準庫IO緩衝區和核心緩衝區的區別
- 緩衝區分析
- Java NIO:緩衝區Java
- getchar緩衝區
- 模擬地下城與勇士(DNF)的裝備強化實現過程
- PHP的輸出緩衝區PHP
- 用apache JCS實現物件緩衝Apache物件
- 手寫AOP實現過程
- 手寫IOC實現過程
- Java模擬賽跑過程Java
- Java NIO 之緩衝區Java
- Unity深度緩衝區指令Unity
- Java整數緩衝區Java
- nginx 緩衝區構造Nginx
- stdio流緩衝區
- javascript模擬實現函式過載JavaScript函式
- 緩衝區溢位漏洞的原理及其利用實戰
- nodejs的tream(流)解析與模擬檔案讀寫流原始碼實現NodeJS原始碼
- MapReduce過程詳解
- 模擬衝刺sprint
- 阻塞(block)過程模擬與分析!BloC
- Node.js Buffer(緩衝區)Node.js
- JavaScript WebGL 幀緩衝區物件JavaScriptWeb物件
- Linux 命令 管道 緩衝區Linux
- log buffer(日誌緩衝區)
- Java NIO 之 Buffer(緩衝區)Java
- Java NIO2:緩衝區Java
- 動態更新——緩衝區物件物件
- promise的模擬實現Promise
- 緩衝區的個人理解!(終結版)
- RMAN的IO記憶體緩衝區記憶體
- 使用Golang泛型構建的無鎖環形緩衝區開源專案Golang泛型
- 小車側方位停車過程的動態模擬matlab模擬Matlab
- 虛擬機器實現dataguard配置過程虛擬機
- 使用KFOD模擬ASM DISK DISCOVERY過程ASM