Неблокируемый файловый ввод-вывод в Java

Я хочу записать в именованный канал (уже созданный), не блокируя его. Мой читатель - еще одно приложение, которое может выйти из строя. Если читатель не работает, я хочу, чтобы приложение писателя продолжало писать в этот именованный канал. Нечто подобное в Java

fopen(fPath, O_NONBLOCK)

, так что когда читатель подходит, он может возобновить работу с того места, где он вышел из строя.

8
задан Howard 10 January 2017 в 16:03
поделиться

3 ответа

Если бы в Java существовала такая вещь, как неблокирующий файловый ввод-вывод, которого нет, то запись в именованный канал, который не читается, вернула бы ноль и ничего не записывала бы. Таким образом, неблокировка не является частью решения.

Существует также проблема, связанная с тем, что именованные каналы имеют конечный размер буфера. Они не являются бесконечными очередями, независимо от того, есть процесс чтения или нет. Я согласен с предложением изучить JMS.

1
ответ дан 5 December 2019 в 17:32
поделиться

Если вы хотите, чтобы каналы оставались активными и ставили сообщения в очередь, вам, вероятно, нужна система обмена сообщениями, а не необработанный канал. В Java стандартный API называется "Java Messaging System" (JMS), и существует множество стандартных реализаций, наиболее распространенной из которых является Apache ActiveMQ. Если вам нужен кроссплатформенный интерфейс, похожий на сокеты, который выполняет буферизацию и восстановление, я могу предложить 0MQ, который, хотя и не является «чистой Java», имеет привязки для многих языков и отличную производительность.

2
ответ дан 5 December 2019 в 17:32
поделиться

Сначала я попытаюсь ответить на ваши вопросы. Далее я попытаюсь показать вам фрагмент кода, который я создал, который решает вашу проблему с помощью блокирующего ввода-вывода.

Ваши вопросы

Хочу написать в именованный канал (уже созданный) без блокировки на читатель

Вам не нужен неблокирующий ввод-вывод для решения вашей проблемы. Я думаю, что это даже не может помочь вам решить вашу проблему. Блокирующий ввод-вывод также будет работать хорошо (возможно, даже лучше, чем неблокирующий ввод-вывод из-за низкого параллелизма). Плюсом является то, что блокирующий ввод-вывод легче программировать. Ваш читатель может/должен оставаться блокирующим.

Мой ридер — еще одно приложение, которое может пойти вниз. Если читатель пойдет вниз, я хочу, чтобы приложение записи продолжайте писать в именованный канал. Так что, когда читатель подойдет, он может возобновиться с того места, где он потерпел неудачу.

просто поместите сообщения в очередь блокировки. Далее запись в именованный канал только когда считыватель читает из него (происходит автоматически из-за блокировки IO). Нет необходимости в неблокирующем файловом вводе-выводе при использовании блокирующей очереди. Данные асинхронно доставляются из очереди блокировки, когда читатель читает, что будет отправлять ваши данные от вашего писателя к читателю.

Что-то вроде fopen(fPath, O_NONBLOCK) в Java

Вам не нужен неблокирующий ввод-вывод на считывателе, даже если вы его использовали. просто используйте блокировку ввода-вывода.

ФРАГМЕНТ КОДА

Создал небольшой фрагмент, который, как мне кажется, демонстрирует ваши потребности.

Компоненты:

  • Writer.java: читает строки из консоли в качестве примера.Когда вы запускаете программу, введите текст, а затем введите, который отправит его в ваш именованный канал. При необходимости автор возобновит запись.
  • Reader.java: читает строки, написанные из именованного канала (Writer.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;
            }
        }
    }
}
8
ответ дан 5 December 2019 в 17:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: