2015-06-03 4 views
1

У меня есть многопоточная программа Java 7 (файл jar), которая использует JDBC для выполнения работы (использует фиксированный пул потоков).Java-параллельная запись из нескольких потоков в один текстовый файл?

Программа работает нормально, и она регистрирует все по мере того, как она переходит в окно командной оболочки оболочки (System.out.printf()) из нескольких параллельных потоков.

В дополнение к выходу на консоль мне также необходимо добавить возможность для этой программы записывать в один простой текстовый файл ASCII-файла - из нескольких потоков.

Объем вывода низкий, файл будет относительно небольшим, как файл журнала, а не файл данных.

Можете ли вы предложить хороший и относительно простой дизайн/подход, чтобы сделать это с использованием функций Java 7 (у меня еще нет Java 8)?

Любые образцы кода также будут оценены.

спасибо большое

EDIT:

Я забыл добавить: в Java 7, используя Files.newOutputStream() статический фабричный метод, как утверждается, поточно - согласно официальной документации Java. Является ли это самым простым вариантом для записи одного файла общего текстового журнала из нескольких потоков?

+1

Почему бы не пойти на стандартный API регистрации, например slf4j http://www.slf4j.org/manual.html? –

+0

Или иначе, если вы хотите придерживаться только jdk api, см. Это: http://stackoverflow.com/questions/5950557/good-examples-using-java-util-logging –

+0

забыли добавить: в Java 7 с помощью Files.newOutputStream() статический заводский метод считается потокобезопасным - согласно официальной документации Java. Является ли это лучшим вариантом для записи одного файла общего текстового журнала из нескольких потоков? –

ответ

0

Держите общую PrintStream ссылку, где вы будете писать в (вместо System.out) и установить его на System.out или канал через к FileOutputStream в зависимости от того, что вы хотите.

Ваш код не будет сильно изменяться (почти совсем) и PrintStream уже синхронизирован.

+1

С другой стороны, 'PrintStream' проглатывает исключения - и я ничего не вижу в * документации *, говоря, что операции синхронизированы ... –

+0

Ну, я подумывал о том, чтобы предложить то, на что вы ответили, но пошел на крайне невысокую производительность , – Kayaman

+0

http://stackoverflow.com/questions/21632585/thread-safety-of-printstream-in-java – Ouney

1

Учитывая, что вы указали, что объем вывода является низким, самым простым вариантом было бы, вероятно, просто написать потокобезопасную запись, которая использует синхронизацию, чтобы убедиться, что только один поток может на самом деле пишите в файл по адресу время.

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

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

+0

спасибо Jon, я внедрил Queue и отдельный поток для записи в файл, кажется, хорошо работает. –

4

Если вы хотите регистрировать выходные данные, почему бы не использовать библиотеку протоколирования, например, например, log4j2? Это позволит вам приспособить свой журнал к вашим конкретным потребностям и может регистрироваться без синхронизации ваших потоков на stdout (вы знаете, что запуск System.out.print включает блокировку на System.out?)

Редактировать: для последнего, если все, что вы регистрируете, является потокобезопасным, и вы в порядке с добавлением LMAX' disruptor.jar к своей сборке, вы можете настроить асинхронные журналы (просто добавить «асинхронный»), в которых будет поток журнала, который будет заботиться обо всем форматировании и записи сообщений (и сохраняя ваши сообщения в журнале), позволяя вашим потокам работать без заминки.

+0

Java имеет регистратор, включенный в JDK (java.util.Logger). В документации упоминалось, что все методы в Logger являются многопоточными. https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html –

+3

Да, но реализация регистратора по умолчанию является медленной по сравнению с log4j2. Конечно, это, вероятно, еще быстрее, чем System.out.println, но почему бы не использовать в настоящее время лучший вариант? Кстати, * вещи * вы должны быть потокобезопасными, потому что, например, если вы регистрируете карту, и она будет изменена тем временем, ваш регистратор может бросить ConcurrentModificationException. В этом случае скопируйте или используйте .toString() в журнале. звонок. – llogiq

Смежные вопросы