2012-04-04 116 views
11

我正在寫一個多線程的Java程序,其中每個線程可能需要將其標準輸出重定向到一個單獨的文件。每個線程都有自己的文件。是否可以在「每個線程」的基礎上重定向System.out,還是在所有線程中對System.out global進行更改?在多線程Java程序中,每個線程都有自己的System.out副本嗎?

+0

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

回答

21

是否有可能重定向的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

3

System.out是靜態的,因此所有線程之間共享相同的實例。

3

你是對的,但不符合你的想法。當一個線程使用

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

5

是否有可能重定向的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

0

是否有可能重定向的System.out「每線程」的基礎上

您可以將它們全部重定向到您的委託,它將負責「每線程」的邏輯。

Here is具有自己的文件輸出的並行JBehave測試的示例。

相關問題