Java: System.setErr после первого setErr не записывает в файл

У меня есть серверная программа, использующая System.setErr () для ведения журнала. У меня проблема с закрытием последнего PrintStream и открытием нового для записи.

Вот как он инициализируется:

File file = new File("file" + "_.txt");
for (int i = 1; file.exists(); i++) {
    file = new File(String.format("file" + "_%d.txt", i));
}

System.setErr(new PrintStream(new BufferedOutputStream(new FileOutputStream(file)), true));

Вот как он перезапускается:

System.err.flush();
System.err.close();
File file = new File("file" + "_.txt");
for (int i = 1; file.exists(); i++) {
    file = new File(String.format("file" + "_%d.txt", i));
}

System.setErr(new PrintStream(new BufferedOutputStream(new FileOutputStream(file)), true));

Проблема в том, что все, что отправляется в новый PrintStream для System.err, не печатается. Печатаются только его части, но большая часть (в нескольких потоках) - нет.

Хотел бы помочь, Спасибо!

Значит, информация соответствующие, не показанная в коде, - это «..в нескольких потоках ..»?

user2864740 09.09.2018 08:03

Кажется, я не понимаю. System.err статичен, не следует ли устанавливать новый PrintStream, чтобы все будущие вызовы System.err печатались в новом потоке?

Justin Q. 09.09.2018 08:06

Гипотеза: проблема («только части [выходного отпечатка]») не возникает, когда потоки не задействованы. Проверьте это; это позволит либо исключить потоки, либо указать, что задействована потоковая передача.

user2864740 09.09.2018 23:18

Также обратите внимание, что хотя System.err является статическим, это не летучий, а весь сброс / закрытие / повторное открытие - это неатомный. Без дополнительного кода (который, вероятно, показывает участие потоков) маловероятно, что «проблема» может быть точно объяснена.

user2864740 09.09.2018 23:19

@ user2864740 Вообще-то об этом не подумал! Это может означать, что мне придется реализовать мою собственную версию System.err, которая является изменчивой. Спасибо за понимание! Завтра протестирую :)

Justin Q. 10.09.2018 08:32

Я подозреваю, что это "может сработать", если использовать что-то вроде: synchronized (..) { PrintStream oldErr = System.err; System.setError(OpenNewStream()); } Sleep_X_Milliseconds(); CloseOldStream(oldErr);. Существует все еще состояние гонки, где System.err еще не загружен новым потоком «до» закрытия, но он должен быть «минимальным» из-за засыпания: в основном, старый поток не должен закрываться, если на него есть ссылки любой . (Там, где есть очень небольшая вероятность, что «новые» данные будут записаны в «старый» файл на очень короткое время.)

user2864740 10.09.2018 22:46

Чтобы обойти состояние гонки, рассмотрите возможность реализации "RedirectableStream"который использует надлежащую защиту синхронизации внутри. Это может быть (например, при запуске программы перед потоками): RedirecatableStream x = ..; System.setError(new PrintStream(x)); и позже на x.targetNewFile("xyz").

user2864740 10.09.2018 22:47

В качестве альтернативы можно было бы злоупотребить тем фактом, что PrintStreamсинхронизируется сам по себе, так что ... synchronized (System.err) { PrintStream oldErr = System.err; System.setError(OpenNewStream()); CloseOldStream(oldErr); }мог бы будет на 100% потокобезопасным, если переназначение System.err вызывается только из одного потока (при вызове из нескольких потоков потребуется вторичная синхронизация) - при этом используется «преимущество» деталей реализации.

user2864740 10.09.2018 22:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
8
64
0

Другие вопросы по теме