[英]Java - Processing file with three threads
ExecutorService executor1 = Executors.newSingleThreadExecutor();
ExecutorService executor2 = Executors.newSingleThreadExecutor();
ExecutorService executor3 = Executors.newSingleThreadExecutor();
ArrayBlockingQueue<String> abq = new ArrayBlockingQueue<String>(1000);
try {
String line;
InputStream is = file.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
String[] values = line.split(",");
List<String> valuesList = Arrays.asList(values);
for(String valueList : valuesList) {
abq.put(valueList);
executor2.execute(new Runnable () {
public void run() {
System.out.println(valueList + Thread.currentThread().getName());
}
});
嗨,我正在嘗試執行以下操作:
我不知道我是否理解你想要做什么,但我會這樣做:我創建了 3 個線程並以不同的方式命名它們,基於我讓它們運行 3 種不同方法的名稱:第一個讀取文件並將結果放入所有 trheads 和 static 共享的 arraylist 中,第二個有一個無限循環(或者如果你想進行一些優化,則每隔特定時間運行一個任務),它總是采用 arraylist 的第一個元素並處理它和將它放在另一個也是共享和靜態的數組列表中,第三個線程也有一個循環(或任務),它總是采用第一個元素並將其打印到文件中。
我會這樣做,但也許我不明白,如果你需要寫信給我
(谷歌翻譯從:意大利語到:英語)
我們正在執行以下兩項任務:
請注意,可能僅在查看某些特定的高吞吐量場景時才需要使用 2 個不同線程順序工作並同步(阻塞)消息切換的方法。 與每個線程的每個任務相關聯的工作通常必須平衡(即占用相似數量的 CPU 周期),這甚至是有益的。 或者,該輸出被寫入例如雲存儲或可能間歇性停止的東西。
您是正確的,您必須使用線程安全隊列在線程之間進行切換! 最簡單的方法是直接實例化和設置兩個線程之間的交互(而不是使用 ExecutorService)。
有關代碼示例,請參見下文。 這里我們假設表示消息的 Java 對象稱為MyMsg
,並且序列化形式在輸入和輸出文件中都是基於String
的:
public class ProcessorExample {
private static final MyMsg END = new MyMsg(); // used to signal file read finished
public void processFile(File inFile, File outFile) {
BlockingQueue<MyMsg> queue = new ArrayBlockingQueue<>(4096);
Thread reader = new Thread(() -> read(queue, inFile), "reader");
Thread writer = new Thread(() -> write(queue, outFile), "writer");
reader.start();
writer.start();
}
private void read(BlockingQueue<MyMsg> queue, File inFile) {
try (BufferedReader reader = new BufferedReader(new FileReader(inFile))) {
String line;
while ((line = reader.readLine()) != null) {
queue.put(deserialize(line)); //surround with try/catch to drop failed messages
}
queue.put(END);
} catch (IOException|InterruptedException e) {
// TODO: Graceful handling of exceptions at file level
}
}
private void write(BlockingQueue<MyMsg> queue, File outFile) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(outFile))) {
MyMsg msg;
while ((msg = queue.take()) != END) {
writer.write(serialize(msg)); //surround with try/catch to drop failed messages
}
} catch (IOException|InterruptedException e) {
// TODO: Graceful handling of exceptions at file level
}
}
private MyMsg deserialize(String str) {
return null; //TODO implement
}
private String serialize(MyMsg msg) {
return null; //TODO implement
}
}
最后的一些想法:
ArrayBlockingQueue
我看到發布了各種解決方案,但我懷疑您是否想將讀取和寫入完全分開。
如果您要並行處理許多文件,那么我將從順序讀取和寫入單個線程開始,這樣就不需要同步,因此您不會浪費 CPU 的潛力。
您可以通過多個線程並行處理多個文件。
我將首先創建一些基准測試,例如使用 JMH,然后在跳入多線程解決方案之前查看實際瓶頸是什么。 如果使用得當,單個 CPU 可以完成大量工作。
如果您使用的是 Linux,那么對於簡單的順序 I/O,您不需要等待磁盤訪問(因此它不是同步的)。 Linux 使用了一種稱為預讀的功能,它會將您的進程將要讀取的數據預取到頁面緩存中。 因此,當您的本地讀取緩沖區耗盡時,它只需要查看頁面緩存以在用戶空間緩沖區中加載下一個數據,因為預讀可能已經將數據加載到頁面緩存中。 對於緩沖 I/O,寫入也首先在用戶空間緩沖區中結束; 一旦緩沖區填滿,它就會被寫入頁面緩存。 只有在未來的某個時刻,臟頁才會寫入磁盤。 現代 NVMe SSD 的順序讀/寫速度非常快(每秒數 GB)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.