Я хочу записать в именованный канал (уже созданный), не блокируя его. Мой читатель - еще одно приложение, которое может выйти из строя. Если читатель не работает, я хочу, чтобы приложение писателя продолжало писать в этот именованный канал. Нечто подобное в Java
fopen(fPath, O_NONBLOCK)
, так что когда читатель подходит, он может возобновить работу с того места, где он вышел из строя.
Если бы в Java существовала такая вещь, как неблокирующий файловый ввод-вывод, которого нет, то запись в именованный канал, который не читается, вернула бы ноль и ничего не записывала бы. Таким образом, неблокировка не является частью решения.
Существует также проблема, связанная с тем, что именованные каналы имеют конечный размер буфера. Они не являются бесконечными очередями, независимо от того, есть процесс чтения или нет. Я согласен с предложением изучить JMS.
Если вы хотите, чтобы каналы оставались активными и ставили сообщения в очередь, вам, вероятно, нужна система обмена сообщениями, а не необработанный канал. В Java стандартный API называется "Java Messaging System" (JMS), и существует множество стандартных реализаций, наиболее распространенной из которых является Apache ActiveMQ. Если вам нужен кроссплатформенный интерфейс, похожий на сокеты, который выполняет буферизацию и восстановление, я могу предложить 0MQ, который, хотя и не является «чистой Java», имеет привязки для многих языков и отличную производительность.
Сначала я попытаюсь ответить на ваши вопросы. Далее я попытаюсь показать вам фрагмент кода, который я создал, который решает вашу проблему с помощью блокирующего ввода-вывода.
Хочу написать в именованный канал (уже созданный) без блокировки на читатель
Вам не нужен неблокирующий ввод-вывод для решения вашей проблемы. Я думаю, что это даже не может помочь вам решить вашу проблему. Блокирующий ввод-вывод также будет работать хорошо (возможно, даже лучше, чем неблокирующий ввод-вывод из-за низкого параллелизма). Плюсом является то, что блокирующий ввод-вывод легче программировать. Ваш читатель может/должен оставаться блокирующим.
Мой ридер — еще одно приложение, которое может пойти вниз. Если читатель пойдет вниз, я хочу, чтобы приложение записи продолжайте писать в именованный канал. Так что, когда читатель подойдет, он может возобновиться с того места, где он потерпел неудачу.
просто поместите сообщения в очередь блокировки. Далее запись в именованный канал только когда считыватель читает из него (происходит автоматически из-за блокировки IO). Нет необходимости в неблокирующем файловом вводе-выводе при использовании блокирующей очереди. Данные асинхронно доставляются из очереди блокировки, когда читатель читает, что будет отправлять ваши данные от вашего писателя к читателю.
Что-то вроде fopen(fPath, O_NONBLOCK) в Java
Вам не нужен неблокирующий ввод-вывод на считывателе, даже если вы его использовали. просто используйте блокировку ввода-вывода.
Создал небольшой фрагмент, который, как мне кажется, демонстрирует ваши потребности.
Компоненты:
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;
}
}
}
}