二十一.线程安全的集合类

线程安全的集合类

List

  • CopyOnWriteArrayList
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class UnsafeList {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("1", "2", "3");
        list.forEach(System.out::println);
        ArrayList<String> list1 = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            new Thread(()->{
                list1.add(UUID.randomUUID().toString().substring(0,4));
                System.out.println(list1);
            },String.valueOf(i)).start();
        }
    }
    //java.util.ConcurrentModificationException 并发修改异常
    //解决方法:
    //1.new Vector<>();
    //2.Collections.synchronizedList();
    //3.new CopyOnWriteArrayList<>(); JUC包下
}
  • new CopyOnWriteArrayList<>():写入时复制,读取时固定,写入时避免覆盖造成数据问题。

CopyOnWriteArraySet

package com.cyl.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
public class Set01 {
    public static void main(String[] args) {
        Set<String> set = Collections.synchronizedSet(new HashSet<>());
        CopyOnWriteArraySet<Object> set1 = new CopyOnWriteArraySet<>();
        for (int i = 1; i <= 10; i++) {
            new Thread(()->{
                set1.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(set1);
            },String.valueOf(i)).start();
        }
    }
}

HashSet底层是什么?

public HashSet() {
    map = new HashMap<>();
}

//add:本质即map的key是无法重复的

public boolean add(E e) {
    return map.put(e,PRESENT)==null;
}
private static final Object PRESENT = new Object();
  • 底层使用了HashMap中的Key。

ConcurrentHashMap

package com.cyl.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
// java.util.ConcurrentModificationException
public class Map01 {
    public static void main(String[] args) {
        //map是这样用的吗?默认等价于什么?new HashMap<>(16,0.75);
        //加载因子,初始化容量(0.75)
        Map<Object, Object> map = new HashMap<>();
        //线程安全的
        ConcurrentHashMap<Object, Object> map1 = new ConcurrentHashMap<>();
        for (int i = 1; i <= 30; i++) {
            new Thread(()->{
                map.put(Thread.currentThread().getName(),
                        UUID.randomUUID().toString().substring(0,5));
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }
}

ConcurrentHashMap原理初探

  • ConcurrentHashMap和HashMap一样都是采用拉链法处理哈希冲突,且都为了防止单链表过长影响查询效率,所以当链表长度超过某一个值时候将用红黑树代替链表进行存储,采用了数组+链表+红黑树的结构
  • 所以从结构上看HashMap和ConcurrentHashMap还是很相似的,只是ConcurrentHashMap在某些操作上采用了CAS + synchronized来保证并发情况下的安全。
  • 说到ConcurrentHashMap处理并发情况下的线程安全问题,这不得不提到Hashtable,因为Hashtable也是线程安全的
  • Hashtable采用对象锁(synchronized修饰对象方法)来保证线程安全,也就是一个Hashtable对象只有一把锁,如果线程1拿了对象A的锁进行有synchronized修饰的put方法,其他线程是无法操作对象A中有synchronized修饰的方法的(如get方法、remove方法等),竞争激烈所以效率低下。
  • ConcurrentHashMap采用CAS+synchronized来保证并发安全性,且synchronized关键字不是用在方法上而是用在了具体的对象上,实现了更小粒度的锁,
  • Hashtable采用的是数组+链表,当链表过长会影响查询效率
  • 而ConcurrentHashMap采用数组+链表+红黑树,当链表长度超过某一个值,则将链表转成红黑树,提高查询效率。

Callable接口

  • callable接口类似于Runnable接口,因为他们都是为其实例可能由另一个线程执行的类设计的。而Runnable不返回结果,也不抛出异常。
  • runnable接口没有返回值,Callable有返回值,可抛出异常
package com.cyl.Callable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyThread thread = new MyThread();
        //适配类
        FutureTask futureTask = new FutureTask(thread);
        new Thread(futureTask,"A").start();
        String s1 = (String) futureTask.get();//获取返回结果
        System.out.println(s1);
    }
}
class MyThread implements Callable<String>{
    @Override
    public String call() throws Exception {
        return "null";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值