Map和CopyOnWriteArrayList

为什么HashMap是线程不安全的

同时put碰撞导致数据丢失

同时put扩容导致数据丢失

死循环造成cpu百分百(JDK7及之前存在)

可以参考:疫苗:JAVA HASHMAP的死循环        漫画版

 

putVal流程

  1. 判断key value不为空
  2. 计算hash值
  3. 根据对应位置节点的类型,来赋值,或者helpTransfer,或者增长链表,或者给红黑树增加节点
  4. 检查 满足阈值就“红黑树化
  5. 返回 oldVal

get流程

  1. 计算hash值
  2. 找到对应位置,根据情况进行:
  3. 直接取值
  4. 红黑树里找值
  5. 遍历链表取值
  6. 返回找到的结果

 

组合操作(不能又get又put)不保证ConcurrentHashMap线程安全

package predecessor;

import java.util.concurrent.ConcurrentHashMap;

public class HashMap implements Runnable{

    private static ConcurrentHashMap<String,Integer> scores = new ConcurrentHashMap<>();

    public static void main(String[] args) throws InterruptedException {
        scores.put("小明",0);
        Thread t1 = new Thread(new HashMap());
        Thread t2 = new Thread(new HashMap());
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(scores);
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            Integer score = scores.get("小明");
            Integer newScore = score+1;
            scores.put("小明",newScore);
        }
    }
}

保证安全,要么用synchronized (class)类锁,要么用replace(key,oldvalue,newvalue)方法

 

CopyOnWriteArrayList

  • 代替Vector和synchronizedList
  • Vector和synchronizedList的锁的粒度太大,并发效率相对比较低,并且迭代时无法编辑
  • 还包括CopyOnWriteArraySet,用来替代同步Set

适用场景

  • 读操作尽可能地快,而写即使慢一些也没有太大关系
  • 比如:黑名单,每日更新,监听器:迭代操作远多于修改操作(读多写少)
  • 不像读写锁只允许读读共享,他是读写锁规则 的升级,读取完全不用加锁,并且写入也不会阻塞读取操作。只有写入和写入之间需要同步等待
  • 缺点是得到的数据有可能不是最新的
  • 因为复制所以要占用双倍内存
  • add方法用reentrantlock加锁,了解Reentrantlock
package predecessor;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListDemo1 {
    public static void main(String[] args) {
        //ArrayList<String> arrayList = new ArrayList<>();
        CopyOnWriteArrayList<String> arrayList = new CopyOnWriteArrayList<>();

        arrayList.add("1");
        arrayList.add("2");
        arrayList.add("3");
        arrayList.add("4");
        arrayList.add("5");
        arrayList.add("6");

        Iterator<String> iterator = arrayList.iterator();
        while (iterator.hasNext()){
            System.out.println(arrayList);
            String next = iterator.next();
            System.out.println(next);
            if (next.equals("2")){
                arrayList.remove("5");
            }
        }
    }
}

[1, 2, 3, 4, 5, 6]
1
[1, 2, 3, 4, 5, 6]
2
[1, 2, 3, 4, 6]
3
[1, 2, 3, 4, 6]
4
[1, 2, 3, 4, 6]
5
[1, 2, 3, 4, 6]
6

 

注意看5这里,即使删除了,他还是找到节点5,说明,修改和迭代分开的。因为他是复制一份出来再进行的操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值