[英]Non-Blocking File IO in Java
我想寫一個命名管道(已經創建)而不會阻塞讀取器。 我的讀者是另一個可能會失敗的應用程序。 如果讀者確實失敗了,我希望編寫器應用程序繼續寫入該命名管道。 像Java這樣的東西
fopen(fPath, O_NONBLOCK)
因此,當讀者出現時,它可能會從失敗的地方恢復。
首先,我試着回答你的問題。 接下來,我將嘗試向您展示我創建的代碼片段,它使用阻止IO來解決您的問題。
我想寫一個命名管道(已經創建)而不會阻塞讀取器
您不需要非阻塞IO來解決您的問題。 我認為它甚至無法幫助您解決問題。 阻止IO也將運行良好(可能甚至比非阻塞IO更好,因為並發性低)。 加號阻止IO更容易編程。 您的讀者可以/應該保持阻止。
我的讀者是另一個可能會失敗的應用程序。 如果讀者確實失敗了,我希望編寫器應用程序能夠寫入命名管道。 因此,當讀者出現時,它可能會從失敗的地方恢復。
只是將消息放入阻塞隊列中。 接下來只有當讀者從中讀取時才寫入命名管道(由於阻塞IO而自動發生)。 使用阻塞隊列時不需要非阻塞文件IO。 當讀者正在閱讀時,數據是從阻塞隊列異步傳遞的,這會將您的數據從您的編寫器發送到閱讀器。
類似於Java中的fopen(fPath,O_NONBLOCK)
您在閱讀器上不需要非阻塞IO,即使您使用它也是如此。 只使用阻塞IO。
創建了一個小片段,我相信它可以展示您的需求。
組件:
Writer.java
import java.io.BufferedWriter;
import java.io.Console;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Writer {
private final BlockingDeque<StringBuffer> queue;
private final String filename;
public static void main(String[] args) throws Exception {
final Console console = System.console();
final Writer writer = new Writer("pipe");
writer.init();
while(true) {
String readLine = console.readLine();
writer.write(new StringBuffer(readLine));
}
}
public Writer(final String filename){
this.queue = new LinkedBlockingDeque<StringBuffer>();
this.filename = filename;
}
public void write(StringBuffer buf) {
queue.add(buf);
}
public void init() {
ExecutorService single = Executors.newSingleThreadExecutor();
Runnable runnable = new Runnable() {
public void run() {
while(true) {
PrintWriter w = null;
try {
String toString = queue.take().toString();
w = new PrintWriter(new BufferedWriter(new FileWriter(filename)), true);
w.println(toString);
} catch (Exception ex) {
Logger.getLogger(Writer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
single.submit(runnable);
}
}
Reader.java
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Reader {
private final BufferedReader br;
public Reader(final String filename) throws FileNotFoundException {
br = new BufferedReader(new FileReader(filename));
}
public String readLine() throws IOException {
return br.readLine();
}
public void close() {
try {
br.close();
} catch (IOException ex) {
Logger.getLogger(Reader.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) throws FileNotFoundException {
Reader reader = new Reader("pipe");
while(true) {
try {
String readLine = reader.readLine();
System.out.println("readLine = " + readLine);
} catch (IOException ex) {
reader.close();
break;
}
}
}
}
如果Java中存在非阻塞文件I / O這樣的事情,那么對未被讀取的命名管道的寫入將返回零並且不寫入任何內容。 因此,非阻塞不是解決方案的一部分。
還存在命名管道具有有限緩沖區大小的問題。 無論是否有閱讀過程,它們都不是無限的隊列。 我同意調查JMS的建議。
您應該能夠在UNIX FIFO上使用NIO的異步write
,就像對任何其他文件一樣:
AsynchronousFileChannel channel = AsynchronousFileChannel.open(...);
Future<Integer> writeFuture = channel.write(...);
... 要么...
channel.write(..., myCompletionHandler);
但是,當FIFO不接受寫入時,我不清楚你想要發生什么。 你想要緩沖嗎? 如果是這樣,您將需要在Java程序中提供它。 你想讓它超時嗎? Java文件寫入沒有簡單的超時選項。
這些都不是不可克服的問題。 如果你確定你可能會得到一些有用的東西。 但我想知道如果你只是使用TCP套接字或JMS隊列,你是否會發現生活更輕松。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.