我有以下代码给出了java.util.concurrentmodificationexception.
我不是处理线程的专家,但是我认为如果我有一个同步列表,那么它应该是线程安全的…
编辑:
这是我方法的完整代码.
@Override
protected List< ExportSchedule > export( List< ExportSchedule > exportSchedules )
{
final HandleSystemDoiAdministrator handleSystemDoiAdministrator = HandleSystemDoiAdministratorFactory.getInstance();
final List< ExportSchedule > successfullyExported = new ArrayList<>();
final List<ExportError> unsuccessfullyExported = Collections.synchronizedList( new ArrayList<ExportError>() );
ExecutorService executorService = Executors.newFixedThreadPool( 10 );
for ( final ExportSchedule exportSchedule : exportSchedules )
{
executorService.execute( new Runnable() {
public void run()
{
String doi = exportSchedule.getDoi().getDoi();
String url = exportSchedule.getDoi().getUrl();
boolean success = handleSystemDoiAdministrator.updateDoiHandle( doi, url );
if ( success )
{
successfullyExported.add( exportSchedule );
}
else
{
if ( handleSystemDoiAdministrator.isWarn() )
{
DoiErrorHelper.persistExportError(
ExportInterface.HANDLE_SERVER,
doi,
"Warning: Error exporting DOI " + doi + " with URL " + url + " to Handle Server: "
+ handleSystemDoiAdministrator.getResponseOutcome().toString(),
exportSchedule.getDoi().getDoiPool() );
}
if ( handleSystemDoiAdministrator.isFatal() )
{
synchronized(unsuccessfullyExported) {
unsuccessfullyExported.add( DoiErrorHelper.createExportError( doi, "Fatal: Error exporting DOI " + doi + " with URL " + url + " to Handle Server: "
+ handleSystemDoiAdministrator.getResponseOutcome().toString(), null, new Date(), exportSchedule.getDoi().getDoiPool().getName(),
exportSchedule.getDoi().getDoiPool().getDoiPrefix(), ExportInterface.HANDLE_SERVER ) );}
}
}
}
} );
}
executorService.shutdown();
try
{
executorService.awaitTermination( 1, TimeUnit.MINUTES );
}
catch ( InterruptedException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return successfullyExported;
}
编辑2:
这是错误:
[exec]
[exec] [#|2014-05-08T10:16:12.951+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=203;_ThreadName=Thread-2;| at java.util.HashMap$HashIterator.nextEntry(HashMap.java:894)|
#]
[exec]
[exec] [#|2014-05-08T10:16:12.951+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=203;_ThreadName=Thread-2;| at java.util.HashMap$EntryIterator.next(HashMap.java:934)|#]
[exec]
[exec] [#|2014-05-08T10:16:12.951+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=203;_ThreadName=Thread-2;| at java.util.HashMap$EntryIterator.next(HashMap.java:932)|#]
[exec]
[exec] [#|2014-05-08T10:16:12.952+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=203;_ThreadName=Thread-2;| at java.util.AbstractMap.toString(AbstractMap.java:518)|#]
[exec]
[exec] [#|2014-05-08T10:16:12.952+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=203;_ThreadName=Thread-2;| at ch.ethz.id.wai.doi.export.handle.DoiExport2HSProcessing$1.r
un(DoiExport2HSProcessing.java:106)|#]
[exec]
[exec] [#|2014-05-08T10:16:12.952+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=203;_ThreadName=Thread-2;| at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoo
lExecutor.java:1145)|#]
[exec]
[exec] [#|2014-05-08T10:16:12.952+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=203;_ThreadName=Thread-2;| at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPo
olExecutor.java:615)|#]
[exec]
[exec] [#|2014-05-08T10:16:12.953+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=203;_ThreadName=Thread-2;| at java.lang.Thread.run(Thread.java:722)|#]
[exec]
[exec] [#|2014-05-08T10:16:28.552+0200|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=157;_ThreadName=Thread-2;|0|#]
[exec]
[exec] [#|2014-05-08T10:16:31.221+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=222;_ThreadName=Thread-2;|Exception in thread "pool-41-thread-10" |#]
[exec]
[exec] [#|2014-05-08T10:16:31.223+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=222;_ThreadName=Thread-2;|java.util.ConcurrentModificationException
[exec] at java.util.HashMap$HashIterator.nextEntry(HashMap.java:894)
[exec] at java.util.HashMap$EntryIterator.next(HashMap.java:934)
[exec] at java.util.HashMap$EntryIterator.next(HashMap.java:932)
[exec] at java.util.AbstractMap.toString(AbstractMap.java:518)
[exec] at ch.ethz.id.wai.doi.export.handle.DoiExport2HSProcessing$1.run(DoiExport2HSProcessing.java:106)
[exec] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
[exec] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
[exec] at java.lang.Thread.run(Thread.java:722)
[exec] |#]
DoiExport2HSProcessing.java是包含方法的类,第106行是将错误添加到列表的位置.
解决方法:
ConcurrentModificationException与同步或线程安全直接无关.多线程将使此异常的条件(参见下文)不可见,但也可能在一个线程中发生!
同步列表可防止您以未定义状态从多个线程访问列表.但是您仍然可以在修改列表时迭代元素.这将导致ConcurrentModificationException.
您不得在迭代过程中使用add(),remove()等修改列表.唯一有效的修改是使用Iterator(remove())或ListIterator(add()和set())的方法!