在多线程Java程序中,每个线程都有自己的System.out副本吗?

问题描述:

我正在写一个多线程的Java程序,其中每个线程可能需要将其标准输出重定向到一个单独的文件。每个线程都有自己的文件。是否可以在“每个线程”的基础上重定向System.out,还是在所有线程中对System.out global进行更改?在多线程Java程序中,每个线程都有自己的System.out副本吗?

+0

您可以使用[AspectJ](http://eclipse.org/aspectj) – 2013-03-20 17:43:43

是否有可能重定向的System.out“每线程”的基础上

上不,它是不可能的。 System.out是静态的,并且每个JVM在JVM最初引导时作为系统类加载器的一部分加载。虽然推荐使用每线程正确的日志记录调用,但我认为有一些原因让你无法做到这一点。这种方式可能是第三方库或其他代码是使用System.out

你可以做的一件事(作为一个激进的建议)是让你自己的PrintStream,代表ThreadLocal<PrintStream>。但是你需要调用所有的方法来让它每线程工作。

最后,如果你问这个是因为你担心并发,System.outPrintStream所以它已经是在幕后​​,可以被多个线程安全地使用。

+0

返回不同的'PrintStream'对象我目前正在寻找命名每个线程,并制作一个自定义的PrintStream,它需要一个Map 。当自定义打印流接收到一个信号以将某些内容打印到屏幕上时,它使用Thread.currentThread来获取当前的Thread对象并在地图中查找它。如果线程是映射中的键,则输出将写入相应的OutputStream,否则将转至默认输出。 – user1258361 2012-04-04 16:30:45

+1

您可以使用java.util.logging(或其他日志框架)和相应的格式化程序来记录线程名称。我强烈建议使用System.out的这种方法。 – Adamski 2012-04-04 16:35:16

+0

我需要根据哪个线程正在运行将标准输出重定向到一个变量位置。线程不输出标准的“日志”错误消息。我看着Java日志记录,我认为这不适合我的问题。 – user1258361 2012-04-04 16:56:01

System.out是静态的,因此所有线程之间共享相同的实例。

你是对的,但不符合你的想法。当一个线程使用

System.out.println(); 

它采用参考System.out的副本,而不是对象的引用这个副本。

这意味着所有线程通常会看到写入输出的相同对象。

注意:此字段不是线程安全的,如果您致电System.setOut(PrintStream)如果使用此操作,则存在潜在的不良竞争情况,其中不同线程拥有不同的System.out本地副本。这不能用来解决这个问题。

是否有可能通过自己的实现是线程特定取代的System.out重定向的System.out“每线程”的基础上

你可以做到这一点。即PrintStream的子类。我已经做了这个记录,我希望每个线程的输出是一致的而不是交错的。例如想象一下,在两个线程中同时打印两个堆栈跟踪。 ;)

+1

你可以在启动任何线程之前控制它,否则你不得不希望它无关紧要。你是什​​么意思'男孩这是误导'? – 2012-04-04 17:11:23

+0

只有一个System.out。你所建议的是你改变System.out取决于线程,这不同于多个System.out。您的建议类似于说有8个CD-ROM和一个CD-ROM驱动器相当于有8个CD-ROM驱动器,因为您可以在需要时切换CD。 CD可以切换出来吗?是。和8个CD驱动器一样吗?没有。 – user1258361 2012-04-04 17:33:14

+0

我建议你改变System.out是一个组件,每个线程的基础上做不同的事情。这与具有多个System.out值不同。我的评论是关于System.out的线程安全性,它允许多个线程由于竞争条件而看到不同的值,这是你不能使用的东西,只会是一个问题。我建议有一个8 CD转换器,它对用户来说是一个驱动器,例如有8个子目录。 – 2012-04-04 17:46:44

是否有可能重定向的System.out“每线程”的基础上

Maia Company一些开发者提供了一个公共的实现,提供了一个“STDOUT”一个PrintStream的本文中的每个线程:“Thread Specific System.out”。

在它们的实现中,它们只覆盖写入方法flush,close和checkError。他们的情况似乎已经足够了。

他们没有需要@Override所有的称为得到它每线程工作方法”作为他的回答表示@Gray

+1

似乎这个链接已经死了,但是你可以在'org.apache.geronimo.gshell.support.gshell-io.SystemOutputHijacker'中找到类似的实现。 [Maven package](https://mvnrepository.com/artifact/org .apache.geronimo.gshell.support/gshell-io/1.0-alpha-2)和[源代码浏览器](http://grepcode.com/file/repo1.maven.org/maven2/org.apache.servicemix。 kernel.gshell/org.apache.servicemix.kernel.gshell.core/1.1.0 /组织/阿帕奇/的geronimo/gshell/IO/SystemOutputHijacker.java) – 2016-07-04 08:53:14

是否有可能重定向的System.out“每线程”的基础上

您可以将它们全部重定向到您的委托,它将负责“每线程”的逻辑。

Here is具有自己的文件输出的并行JBehave测试的示例。