多线程并发修改集合案例

        //单线程使用  修改集合
        ArrayList arrayList = new ArrayList();
        for (int i = 0; i < 100; i++) {
            arrayList.add(i);
        }
        int batch = 10;
        int size = arrayList.size();
        if (0 < size && size <= batch) {
            List list = arrayList.subList(0, size);
            System.out.println(">>>>>>>>>>>>:" + JSON.toJSONString(list));
        } else {
            int flag = size % batch == 0 ? size / batch : size / batch + 1;
            for (int i = 0; i < flag; i++) {
                if (i == flag - 1) {
                    List list = arrayList.subList(0, arrayList.size());
                    System.out.println(">>>>>>>>>>>>:" + JSON.toJSONString(list));
                    arrayList.removeAll(list);
                } else {
                    List list = arrayList.subList(0, batch);
                    System.out.println(">>>>>>>>>>>>:" + JSON.toJSONString(list));
                    arrayList.removeAll(list);
                }
            }
        }
        //多线程 步长【0,10,20,30,40】修获取 集合上的位置各索引的值
        ArrayList arrayList = new ArrayList();
        for (int i = 0; i < 10000; i++) {
            arrayList.add(i);
        }
        int batch = 10;
        int size = arrayList.size();
        if (0 < size && size <= batch) {
            List list = arrayList.subList(0, size);
            threadPoolExecutor.submit(() -> {
                print0(list);
            });
        } else {
            int flag = size % batch == 0 ? size / batch : size / batch + 1;
            for (int i = 0; i < flag; i++) {
                List list;
                if (i == flag - 1) {
                    list = arrayList.subList(i * batch, arrayList.size());
                } else {
                    list = arrayList.subList(i * batch, (i + 1) * batch);
                }
                threadPoolExecutor.submit(() -> {
                    print0(list);
                });
            }
        }

 

下面这个是错误案例:

 

        //多线程并发修改
        ArrayList arrayList = new ArrayList();
        for (int i = 0; i < 100; i++) {
            arrayList.add(i);
        }
//        ArrayList:
//        System.arraycopy
//        System.arraycopy(elementData, 0, a, 0, size);


//        array.copy 【里面实现使用】浅复制  索引修改后对原数据造成影响

//        CopyOnWriteArrayList
//        es = Arrays.copyOf(es, es.length, Object[].class);

        CopyOnWriteArrayList copyOnWriteArrayList = new CopyOnWriteArrayList(arrayList);
        int batch = 10;
        int size = copyOnWriteArrayList.size();
        if (0 < size && size <= batch) {
            List list = copyOnWriteArrayList.subList(0, size);
            threadPoolExecutor.submit(() -> {
                print0(list);
            });
        } else {
            int flag = size % batch == 0 ? size / batch : size / batch + 1;
            for (int i = 0; i < flag; i++) {
                List list;
                if (i == flag - 1) {

                    list = copyOnWriteArrayList.subList(0, copyOnWriteArrayList.size());
                } else {

                    list = copyOnWriteArrayList.subList(0, batch);
                }

                threadPoolExecutor.submit(() -> {
                    //每次执行的都是0-9个元素
                    print0(list);
                    //并发修改异常
                    copyOnWriteArrayList.removeAll(list);
                });

            }
        }

 

        //迭代器不会报错  但是不能满足多线程批量处理
        CopyOnWriteArrayList copyOnWriteArrayList = new CopyOnWriteArrayList(arrayList);

            Iterator iterator = copyOnWriteArrayList.iterator();
            while (iterator.hasNext()){
                Object next = iterator.next();
                System.out.println(":::::::::"+next);
                copyOnWriteArrayList.remove(next);
            }
            System.out.println(":::"+JSON.toJSONString(copyOnWriteArrayList));

 

 

 优化后

    static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),  // 根据 CPU 核心数设置核心线程数
            Runtime.getRuntime().availableProcessors() * 2,  // 最大线程数设为核心线程数的两倍
            100, TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(1000),  // 调整队列容量
            new ThreadPoolExecutor.CallerRunsPolicy());
    static Semaphore semaphore = new Semaphore(8);


    public static void main(String[] args) {
        //多线程并发修改
        ArrayList arrayList = new ArrayList();
        for (int i = 0; i < 100; i++) {
            arrayList.add(i);
        }
//        ArrayList:
//        System.arraycopy
//        System.arraycopy(elementData, 0, a, 0, size);


//        array.copy 【里面实现使用】浅复制  索引修改后对原数据造成影响【尤其是引用对象】,【建议复制一个新的集合,进行操作,这样两个集合就互不影响了】

        //对list操作,就不会影响list0[非引用对象]
//        ArrayList list=new ArrayList();
//        ArrayList list0=new ArrayList(list);


//        CopyOnWriteArrayList
//        es = Arrays.copyOf(es, es.length, Object[].class);

        CopyOnWriteArrayList copyOnWriteArrayList = new CopyOnWriteArrayList(arrayList);
        int batch = 10;
        int size = copyOnWriteArrayList.size();
        if (0 < size && size <= batch) {
            List list = copyOnWriteArrayList.subList(0, size);
            threadPoolExecutor.submit(() -> {
                log.info(">>>>>>>>>>>>>>:{}", JSON.toJSONString(list));
            });
        } else {
            int flag = size % batch == 0 ? size / batch : size / batch + 1;
            for (int i = 0; i < flag; i++) {
                List list;
                if (i == flag - 1) {
                    list = copyOnWriteArrayList.subList(i * batch, copyOnWriteArrayList.size());
                } else {
                    list = copyOnWriteArrayList.subList(i * batch, (i + 1) * batch);
                }
                threadPoolExecutor.submit(() -> {
                    //每次执行的都是0-9个元素
                    List<Integer> localCopy = new ArrayList<>(list);  // 创建当前批次数据的本地副本

                    log.info(">>>>>>>>>>>>>>:{}", JSON.toJSONString(localCopy));
                    //并发修改异常
                    copyOnWriteArrayList.removeAll(localCopy);
                });

            }
        }
        threadPoolExecutor.shutdown();
        while (true) {
            try {
                if (threadPoolExecutor.getActiveCount() == 0 && threadPoolExecutor.getQueue().size() == 0) {
                    break;
                }
                Thread.sleep(1000);
                log.info("当前活动线程数:{},任务队列剩余任务数:{},已完成任务数:{}",
                        threadPoolExecutor.getActiveCount(),
                        threadPoolExecutor.getQueue().size(),
                        threadPoolExecutor.getCompletedTaskCount());

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("线程池等待异常", e);
            }
        }
    }

 

 
posted @ 2023-07-24 22:14  余生请多指教ANT  阅读(70)  评论(0)    收藏  举报