Подтвердить что ты не робот

В многопоточной Java-программе каждый поток имеет свою собственную копию System.out?

Я пишу многопоточную Java-программу, где каждый поток потенциально нуждается в его стандартном выходе, перенаправленном в отдельный файл. Каждый поток будет иметь свой собственный файл. Можно ли перенаправить System.out по принципу "по потоку" или внести изменения в System.out глобально для всех потоков?

4b9b3361

Ответ 1

Можно ли перенаправить System.out на основе "per-thread"

Нет, это невозможно. System.out является статическим, и на JVM есть один, который загружается как часть загрузчика системного класса при первоначальной загрузке JVM. Хотя, конечно, использование правильных протоколов вызовов для каждой темы рекомендуется, я предполагаю, что есть причины, по которым вы не можете этого сделать. Вероятно, сторонняя библиотека или другой код - это то, что использует System.out таким образом.

Одна вещь, которую вы могли бы сделать (как радикальное предложение), - сделать свой собственный PrintStream, который делегирует значение ThreadLocal<PrintStream>. Но вам нужно будет @Override всех методов, вызываемых для работы в потоке.

Наконец, если вы спрашиваете об этом, потому что вас беспокоит concurrency, System.out - это PrintStream, поэтому он уже synchronized находится под обложками и может безопасно использоваться несколькими потоками.

Ответ 2

Можно ли перенаправить System.out на основе "per-thread"

Некоторые разработчики из Maia Company предоставили публичную реализацию PrintStream, которая предоставляет одну "STDOUT" для каждой темы в этой статье: " Thread Specific System.out".

В своей реализации они переопределяют только методы записи, flush, close и checkError. В их случае, похоже, достаточно.

Им не "необходимо @Override всех методов, вызываемых для работы в потоке", как указано @Gray в его ответе.

Ответ 3

System.out является статическим, поэтому один и тот же экземпляр разделяется между всеми потоками.

Ответ 4

Вы правы, но не так, как думаете. Когда поток использует

System.out.println();

Требуется копия ссылки System.out, но не копия объекта, на который ссылаются эти ссылки.

Это означает, что все потоки обычно видят один и тот же объект для записи для вывода.

Примечание. Эти поля небезопасны по потоку, и если вы вызываете System.setOut(PrintStream) Если вы используете это, существует потенциальное нежелательное условие гонки, когда разные потоки имеют разные локальные копии System.out. Это не может быть использовано для решения этого вопроса.

Можно ли перенаправить System.out на основе "per-thread"

Вы можете сделать это, заменив System.out своей собственной реализацией, которая зависит от потока. то есть подкласс класса PrintStream. Я сделал это для ведения журнала, где я хотел, чтобы каждый поток был последовательным, а не чередующимся. например Представьте себе печать двух трасс стека в двух потоках одновременно.;)