鉴于以下内容:
public class CConsole {
public static PrintWriter pw = new PrintWriter(System.out, true);
}
CConsole.pw.format("%d %d", x, y)
线程安全吗?也就是说,多个线程可以使用此调用吗?它被描述为线程安全的位置。我在PrintWriter类描述和format()方法描述中都没有看到它。
答案 0 :(得分:10)
这个问题没有一个简单的答案......
Writer
,它是PrintWriter
的超类,在其构造函数文档中明确提到所有关键部分在Writer
实例本身或显式指定的对象上同步。因此Writer
显然是线程安全的......
不幸的是,PrintWriter
子类文档没有明确地提出这样的承诺。它继承了Writer
锁定对象,但是无法知道任何其他或重写的方法是否仍然是线程安全的。
另一方面,据我所知,Sun/OpenJDK PrintWriter
implementation包含synchronized
几乎所有方法中的块。 但是这似乎不是明确记录的行为。
我宁愿安全地玩它并假设PrintWriter
不是线程安全的,而不是依赖于未记录的行为并且从长远来看后悔......
答案 1 :(得分:8)
这不是完全相同的问题,并且没有给出任何证据。
它还说PrintWriter是没有资格的线程安全的,而另一个答案有资格。在我看来,这需要澄清。
由于OP不理解(或者可能不相信)链接问题的答案,我将重申它们。
主要规范(即javadocs)不说明该类是否是线程安全的。
从阅读源代码可以清楚地看出,在所有相关操作都已正确同步的意义上,它是线程安全的。
在上述意义上,Oracle不太可能故意改变实现以使其成为非线程安全的。
但是,有些用例PrintWriter
可能不完全是线程安全的:
如果多个线程使用单个PrinterWriter
,则结果可能是线程输出的不可预测的交错;例如如果他们使用print而不是println。
如果您有多个PrintWriter
个对象包装相同的基础流,可能会因PrintWriter
内部使用BufferedWriter
而导致问题。
如果您继承PrintWriter
,事情可能会发生变化。
总之,当前PrintWriter
实现(在Oracle / OpenJDK代码库中)是线程安全的,但在某些情况下仍需要小心。其他第三方Java实现(即不是从OpenJDK源代码树派生)也可能不是线程安全的。
涉及多个线程写入同一底层流的应用程序的线程安全始终是细微的...
请注意@KazekageGaara发现的引用......
“多次写入基础输出流的
PrintWriter
的所有方法都在内部处理同步,因此PrintWriter
个对象是线程安全的。”
...来自Mark Grand和Jonathan Knudsen的O'Reilly教科书 - “Java Fundamental Classes Reference”。由于这不是正式的Sun / Oracle出版物,因此它绝不是最终的。
答案 2 :(得分:2)
是的,它是线程安全的。我不明白为什么有些人告诉它不是线程安全的。 它肯定有'lock'成员,它的方法在该锁对象下完全同步。
有人说PrintWriter.print方法不是线程安全的,但它是错误的。 PrintWriter.print调用write(),这绝对是线程安全的。 我们都知道write方法在'lock'下是同步的。 因此print方法是隐式/自然线程安全的。
PrintWriter.println应该自己同步,因为它调用print()和println(), 两者都是“独立的”线程安全的。
答案 3 :(得分:1)
取自here,其中一行代表:
多次写入底层输出流的PrintWriter的所有方法都在内部处理同步,因此PrintWriter对象是线程安全的。
答案 4 :(得分:1)
{
public void print(Object obj)
{
write(String.valueOf(obj));
}
/* Methods that do terminate lines */
}
打印未同步...
因此,如果您使用的是print方法,请写下您自己的“我的作家”并同步它。
或者其他
如果你使用println()....然后它同步..
{
public void println(Object x) {
String s = String.valueOf(x);
synchronized (lock) {
print(s);
println();
}
}
}
答案 5 :(得分:0)