IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 二十一.线程安全的集合类 -> 正文阅读

[Java知识库]二十一.线程安全的集合类

线程安全的集合类

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";
    }
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 13:57:03  更:2021-09-27 13:59:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:26:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码