欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java.util.ConcurrentModificationException

程序员文章站 2022-06-23 12:50:34
...

    /**
     * 线程的分配,
     * 1.获取redis中的所有文件目录,存入集合中
     * 2.分配不同线程进行监听,
     * 3. 对redis里最后修改时间与ftp等时间戳进行比较是否发生改变
     * 3.1 时间戳发生改变走vfs2逻辑,判断修改的是否是文件夹
     * 3.1.1 是文件夹将文件夹路径添加到redis
     * 3.1.2 发生改变的是文件 则走推送程序
     * 3.2 时间戳为发生改变不处理
     * 4. 判断时间片是否结束,结束进入下一个时间片 ,回到步骤一
     * <p>
     * //     * @param threadPoolExecutor 线程池
     * //     * @param dirNum             每个线程分配的目录数
     * //     * @param timeSlice          时间片
     * <p>
     * 单个线程中如果出现新增目录,
     * 直接添到redis中,下一个时间片执行查询redis操作,添加到监听中
     * 如果监听到 变化的是文件,则直接走推送程序
     * ThreadPoolExecutor threadPoolExecutor, int dirNum, int timeSlice
     */
    public void allotThread(ThreadPoolExecutor threadPoolExecutor, FTPClient ftpClient) {
        //*  1.获取redis中的所有文件目录,存入集合中
        Set keySet = redisTemplate.keys("*");
        List<String> keyList = new ArrayList<>(keySet);
        List<String> subList = new ArrayList<>();
        int pointsDataLimit = 10;
        int size = keyList.size();
        //  2.分配不同线程进行监听,
        for (int i = 0; i < size; i++) {
            int finalI = i;
            subList.add(keyList.get(i));
            if (pointsDataLimit == subList.size() || i == size - 1) {

                threadPoolExecutor.execute(new Runnable() {
                    @SneakyThrows
                    @Override
                    public void run() {

                        //                 3. 对redis里最后修改时间与ftp等时间戳进行比较是否发生改变
                        for (String pathName : subList) {
                            FTPFile[] ftpFile = ftpClient.listFiles(pathName);
//
//                            }

                        }

//                            *      3.1 时间戳发生改变走vfs2逻辑,判断修改的是否是文件夹
                        monitor();
//                            *          3.1.1 是文件夹将文件夹路径添加到redis
                        RedisOperations();
//                            *          3.1.2 发生改变的是文件 则走推送程序
                        filePush();
//     *      3.2 时间戳为发生改变不处理

                    }
                });
                subList.clear();
            }
        }
        List list = redisTemplate.opsForValue().multiGet(keyList);
//        System.out.println(list);


    }

上述代码是为了给redis中的多个路径,开启不同的线程进行监听,每十个路径开启一个线程,其中报错如下:

java.util.ConcurrentModificationException

 

 

错误原因见:

主要是由于list进行的clear操作时,会调用remove方法,而我们多个线程之间又会同时进行添加操作,出现并发异常。具体代码可以查看ArrayList相关代码

解决方案:

替换ArrayList为JUC中的CopyOnWriteArrayList

 

相关标签: # Java并发编程