I think the graph below more or less tells the story.
There is absolutely no performance difference regarding which Writer you choose. That's the short story anyway.
The longer story goes something like this...
According to the JDK 7 documentation for StringWriter, it is backed by a StringBuffer, which is thread-safe. However the CharArrayWriter documentation says it is backed by a simple char array. This may lead one to think that CharArrayWriter is not thread safe. That's what I thought as there is no mention of it otherwise.
You'd be wrong if you thought that CharArrayWriter is not thread safe. Examining the code reveals that all the critical parts of the code are wrapped with a synchronized block. This makes it equivalent to StringWriter's thread-safe StringBuffer. CharArrayWriter is thread safe.
I did investigate a little bit more and even wrote some code that used a single CharArrayWriter between multiple threads to see if I could produce inconsistent appends, this didn't not happen in any of my tests. I used a regex pattern to test my generated string after every test.
This is the code I used to test. Swap the StringWriter/CharArrayWriter as needed.
WriterTest.java
import java.io.CharArrayWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WriterTest {
private static Pattern matchPattern = Pattern.compile("(Test)+");
public static final void main(String[] args)
throws InterruptedException
{
int runs = 1000000;
int tests = 100;
int threads = 10;
multiThreadTest(tests, runs, threads);
}
private static void multiThreadTest(int tests, int runs, int threadsCount)
throws InterruptedException
{
Thread[] threads = new Thread[threadsCount];
for (int j = 0; j < tests; j++) {
CharArrayWriter writer = new CharArrayWriter();
for (int i = 0; i < threadsCount; i++) {
threads[i] = new WriterThread(writer, runs);
}
long startTime = System.currentTimeMillis();
for (int i = 0; i < threadsCount; i++) {
threads[i].start();
}
for (int i = 0; i < threadsCount; i++) {
threads[i].join();
}
String str = writer.toString();
long endTime = System.currentTimeMillis();
Matcher m = matchPattern.matcher(str);
System.out.println(endTime-startTime + "\t" + m.matches());
}
}
static class WriterThread extends Thread {
CharArrayWriter writer;
int runs;
public WriterThread(CharArrayWriter writer, int runs) {
this.writer = writer;
this.runs = runs;
}
@Override
public void run() {
for (int i = 0; i < runs; i++) {
writer.append("Test");
}
}
}
}
The only discernible difference I could see is with CharArrayWriter you can get access to the backing char array (or copy of it at least) directly whereas its a little bit more work to get the char array when using StringWriter.
I was a little surprised that CharArrayWriter is thread safe and would like to see an unsynchronized implementation of a string based writer in the JDK in the future.
-i