java - 是什么导致使用 Collections.synchronizedList 的 java.util.concurrentmodificationexception?

标签 java multithreading synchronization

我有以下代码,它给出了 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())!

关于java - 是什么导致使用 Collections.synchronizedList 的 java.util.concurrentmodificationexception?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23536074/

相关文章:

java - 如何使用 ALPN 通过 SPDY 运行 Jetty?

c++ - 使用 std::async() 和 std::move() 将数据异步传递给另一个线程

c# - 从另一个类中的另一个线程更新文本框内容。 C#、WPF

c++ - 尝试跨多个进程使用 Boost.Interprocess 消息队列时的断言

ios - 同步 iOS 设备和索尼运动相机 HDR-AS200V。获取完整的有声电影

java - 如何从eclipse中的java Restful服务连接到sqlserver数据库

java - 在数组上使用 next() 方法

java - Nashorn 的 Object.bindProperties() 方法

.net - .NET UI 元素线程限制的原因

concurrency - 互斥与同步之间的区别?