Java多线程(六)JUC包功能

在多线程环境下,操作ArrayList等非线程安全的集合可能导致数据异常。解决此类问题,可以使用线程安全的集合,如Vector、Collections.synchronizedList包装的ArrayList,或者采用CopyOnWriteArrayList、CopyOnWriteArraySet和ConcurrentHashMap。CopyOnWrite策略在写入时复制原有数据,确保读写互不干扰,尤其适用于读多写少的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、多线程下集合类型安全方案

产生原因:

多线程并发场景下,操作如 ArrayList 这种不安全的集合会出现问题,可能后面写入的会覆盖前面的

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 多线程并发场景下,操作 ArrayList 不安全
 */
public class DemoList {

    public static void main(String[] args) {

        //并发下 ArrayList 不安全
        List<String> list = new ArrayList<>();

        for (int i = 1; i <= 100; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }
}

会出现异常 :ConcurrentModificationException

什么是CopyOnWrite

多线程调用的时候:
读取场景:直接对数据进行读取
写入场景:写入的情况将原先的复制一份,在复制的上面进行写入,写入完成,将此数据覆盖元原先的数据
目的:在写入时避免覆盖,造成数据问题

1、List 多线程解决方案

解决方案:

  • List<String> list = new Vector<>();
  • List<String> list = Collections.synchronizedList(new ArrayList<>());
  • List<String> list = new CopyOnWriteArrayList<>(); 

 推荐使用:CopyOnWriteArrayList

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 多线程并发场景下,操作 ArrayList 不安全
 */
public class DemoList {

    public static void main(String[] args) {

        //并发下 ArrayList 不安全
        //List<String> list = new ArrayList<>();
        /**
         * 解决方案:
         * 1、List<String> list = new Vector<>();
         * 2、List<String> list = Collections.synchronizedList(new ArrayList<>());
         * 3、List<String> list = new CopyOnWriteArrayList<>();
         */
        List<String> list = new CopyOnWriteArrayList<>();

        // CopyOnWrite:写入时复制 COW 计算机程序设计领域的一种优化策略
        // 多线程调用的时候:
        // 读取场景:直接对数据进行读取
        // 写入场景:写入的情况将原先的复制一份,在复制的上面进行写入,写入完成,将此数据覆盖元原先的数据
        // 目的:在写入时避免覆盖,造成数据问题

        for (int i = 1; i <= 100; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }
}

2、Set 多线程解决方案

解决方案:

  • Set<String> set = Collections.synchronizedSet(new HashSet<>());
  • CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();

 推荐使用:CopyOnWriteArraySet

import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 多线程并发场景下,操作 HashSet 不安全
 */
public class DemoSet {

    public static void main(String[] args) {

        //并发下 HashSet 不安全
//        Set<String> set = new HashSet<>();
        /**
         * 解决方案:
         * 1、Set<String> set = Collections.synchronizedSet(new HashSet<>());
         * 2、CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
         */
        CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();

        for (int i = 1; i <= 100; i++) {
            new Thread(() -> {
                set.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(set);
            }, String.valueOf(i)).start();
        }
    }
}

3、Map 多线程解决方案

解决方案:

  • Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
  • Map<String, String> map = new ConcurrentHashMap<>();

 推荐使用:ConcurrentHashMap

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 多线程并发场景下,操作 HashMap 不安全
 */
public class DemoMap {

    public static void main(String[] args) {

        //并发下 HashSet 不安全
//        Map<String, String> map = new HashMap<>();
        /**
         * 解决方案:
         * 1、Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
         * 2、Map<String, String> map = new ConcurrentHashMap<>();
         */
        Map<String, String> map = new ConcurrentHashMap<>();

        for (int i = 1; i <= 100; i++) {
            new Thread(() -> {
                map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 5));
                System.out.println(map);
            }, String.valueOf(i)).start();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值