Skip to content

Commit 241a9e4

Browse files
committed
CSVPrinter now uses an internal lock instead of synchronized methods
1 parent d65785f commit 241a9e4

File tree

2 files changed

+72
-41
lines changed

2 files changed

+72
-41
lines changed

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
<release version="1.14.1" date="YYYY-MM-DD" description="This is a feature and maintenance release. Java 8 or later is required.">
4444
<!-- FIX -->
4545
<action type="fix" issue="CSV-318" dev="ggregory" due-to="Joseph Shraibman, Gary Gregory">CSVPrinter.printRecord(Stream) hangs if given a parallel stream.</action>
46+
<action type="fix" issue="CSV-318" dev="ggregory" due-to="Joseph Shraibman, Gary Gregory">CSVPrinter now uses an internal lock instead of synchronized methods.</action>
4647
<!-- ADD -->
4748
<!-- UPDATE -->
4849
<action type="update" dev="ggregory" due-to="Gary Gregory">Bump commons-io:commons-io from 2.18.0 to 2.19.0.</action>

src/main/java/org/apache/commons/csv/CSVPrinter.java

Lines changed: 71 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,14 @@ public void close(final boolean flush) throws IOException {
151151
* @throws IOException
152152
* If an I/O error occurs
153153
*/
154-
private synchronized void endOfRecord() throws IOException {
155-
println();
156-
recordCount++;
154+
private void endOfRecord() throws IOException {
155+
lock.lock();
156+
try {
157+
println();
158+
recordCount++;
159+
} finally {
160+
lock.unlock();
161+
}
157162
}
158163

159164
/**
@@ -196,9 +201,14 @@ public long getRecordCount() {
196201
* @throws IOException
197202
* If an I/O error occurs
198203
*/
199-
public synchronized void print(final Object value) throws IOException {
200-
format.print(value, appendable, newRecord);
201-
newRecord = false;
204+
public void print(final Object value) throws IOException {
205+
lock.lock();
206+
try {
207+
format.print(value, appendable, newRecord);
208+
newRecord = false;
209+
} finally {
210+
lock.unlock();
211+
}
202212
}
203213

204214
/**
@@ -222,34 +232,39 @@ public synchronized void print(final Object value) throws IOException {
222232
* @throws IOException
223233
* If an I/O error occurs
224234
*/
225-
public synchronized void printComment(final String comment) throws IOException {
226-
if (comment == null || !format.isCommentMarkerSet()) {
227-
return;
228-
}
229-
if (!newRecord) {
230-
println();
231-
}
232-
appendable.append(format.getCommentMarker().charValue()); // Explicit (un)boxing is intentional
233-
appendable.append(SP);
234-
for (int i = 0; i < comment.length(); i++) {
235-
final char c = comment.charAt(i);
236-
switch (c) {
237-
case CR:
238-
if (i + 1 < comment.length() && comment.charAt(i + 1) == LF) {
239-
i++;
240-
}
241-
// falls-through: break intentionally excluded.
242-
case LF:
235+
public void printComment(final String comment) throws IOException {
236+
lock.lock();
237+
try {
238+
if (comment == null || !format.isCommentMarkerSet()) {
239+
return;
240+
}
241+
if (!newRecord) {
243242
println();
244-
appendable.append(format.getCommentMarker().charValue()); // Explicit (un)boxing is intentional
245-
appendable.append(SP);
246-
break;
247-
default:
248-
appendable.append(c);
249-
break;
250243
}
244+
appendable.append(format.getCommentMarker().charValue()); // Explicit (un)boxing is intentional
245+
appendable.append(SP);
246+
for (int i = 0; i < comment.length(); i++) {
247+
final char c = comment.charAt(i);
248+
switch (c) {
249+
case CR:
250+
if (i + 1 < comment.length() && comment.charAt(i + 1) == LF) {
251+
i++;
252+
}
253+
// falls-through: break intentionally excluded.
254+
case LF:
255+
println();
256+
appendable.append(format.getCommentMarker().charValue()); // Explicit (un)boxing is intentional
257+
appendable.append(SP);
258+
break;
259+
default:
260+
appendable.append(c);
261+
break;
262+
}
263+
}
264+
println();
265+
} finally {
266+
lock.unlock();
251267
}
252-
println();
253268
}
254269

255270
/**
@@ -260,11 +275,16 @@ public synchronized void printComment(final String comment) throws IOException {
260275
* @throws SQLException If a database access error occurs or this method is called on a closed result set.
261276
* @since 1.9.0
262277
*/
263-
public synchronized void printHeaders(final ResultSet resultSet) throws IOException, SQLException {
264-
try (IOStream<String> stream = IOStream.of(format.builder().setHeader(resultSet).get().getHeader())) {
265-
stream.forEachOrdered(this::print);
278+
public void printHeaders(final ResultSet resultSet) throws IOException, SQLException {
279+
lock.lock();
280+
try {
281+
try (IOStream<String> stream = IOStream.of(format.builder().setHeader(resultSet).get().getHeader())) {
282+
stream.forEachOrdered(this::print);
283+
}
284+
println();
285+
} finally {
286+
lock.unlock();
266287
}
267-
println();
268288
}
269289

270290
/**
@@ -273,9 +293,14 @@ public synchronized void printHeaders(final ResultSet resultSet) throws IOExcept
273293
* @throws IOException
274294
* If an I/O error occurs
275295
*/
276-
public synchronized void println() throws IOException {
277-
format.println(appendable);
278-
newRecord = true;
296+
public void println() throws IOException {
297+
lock.lock();
298+
try {
299+
format.println(appendable);
300+
newRecord = true;
301+
} finally {
302+
lock.unlock();
303+
}
279304
}
280305

281306
/**
@@ -292,9 +317,14 @@ public synchronized void println() throws IOException {
292317
* If an I/O error occurs
293318
*/
294319
@SuppressWarnings("resource")
295-
public synchronized void printRecord(final Iterable<?> values) throws IOException {
296-
IOStream.of(values).forEachOrdered(this::print);
297-
endOfRecord();
320+
public void printRecord(final Iterable<?> values) throws IOException {
321+
lock.lock();
322+
try {
323+
IOStream.of(values).forEachOrdered(this::print);
324+
endOfRecord();
325+
} finally {
326+
lock.unlock();
327+
}
298328
}
299329

300330
/**

0 commit comments

Comments
 (0)