JUC并发编程——集合类不安全及Callable(基于狂神说的学习笔记)

集合类不安全

List不安全

package unsafe;import PC.A;import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;// ArrayList线程不安全,在多线程下使用ArrayList会报错:
// java.util.ConcurrentModificationException 并发修改异常
public class ListTest {public static void main(String[] args) {// 并发下ArrayList 不安全/*** 解决方案:* 1、List<String> list= new Vector<>();* 实际上,Vector在jdk1.0就已经出来了,ArrayList在jdk1.2才出来* Vector实际上就是在add时将方法synchronized锁起来了* 2、List<String> list = Collections.synchronizedList(new ArrayList<>());// 通过工具类将其转换乘synchronized保证线程安全* 3、List<String> list = new CopyOnWriteArrayList<>();*///List<String> list = new ArrayList<>();//List<String> list = Collections.synchronizedList(new ArrayList<>());List<String> list = new CopyOnWriteArrayList<>();// CopyOnWrite 写入时复制 COW 计算机程序设计领域的一种优化策略// 多个线程调用的时候 list,读取的时候,固定的,写入的时候可能会覆盖// 在写入的时候避免覆盖,造成数据问题// CopyOnWriteArrayList比Vector的优势在于,copyOnWriteArrayList在并发下效率要比vector更高,因为CopyOnWriteArrayList使用的是写时复制策略,而非使用synchronized锁for (int i = 1; i <= 10; i++) {new Thread(()->{list.add(UUID.randomUUID().toString().substring(0,5));System.out.println(list);},String.valueOf(i)).start();}}
}

CopyOnWriteArrayList与vector对比,以下来自CSDN智能助手的回答:

Java中的CopyOnWriteArrayList和Vector都是线程安全的动态数组,可以在多线程环境下使用。

CopyOnWriteArrayList使用了一种特殊的写时复制机制,它在对数组进行修改时,会创建一个新的副本,而不是直接在原数组上进行修改。这样可以确保在多线程并发修改时不会发生问题。然而,由于每次修改都需要创建一个新的副本,所以在写入操作频繁的情况下,CopyOnWriteArrayList的性能可能会比较低。

Vector是一个同步的动态数组,它使用了synchronized关键字来保证多线程安全。当多个线程同时修改Vector时,每个线程会依次获得锁,并按顺序执行相应的修改操作。虽然Vector具有线程安全性,但在高并发情况下,由于需要频繁的获取锁和释放锁,可能会导致性能下降。

因此,如果在多线程环境下需要频繁进行读操作,而写操作较少的情况下,CopyOnWriteArrayList可能会更适合。而如果需要频繁进行写操作或者对线程安全性要求不是非常高,可以考虑使用Vector。

而后笔者在IDEA中翻阅关于CopyOnWriteArralyList的add()方法源码发现,它还是使用synchronized关键字,源码如下:

/*** Appends the specified element to the end of this list.** @param e element to be appended to this list* @return {@code true} (as specified by {@link Collection#add})*/
public boolean add(E e) {synchronized (lock) {Object[] es = getArray();int len = es.length;es = Arrays.copyOf(es, len + 1);es[len] = e;setArray(es);return true;}
}

然后笔者去查了文心一言的回答,得到的答案依然是CopyOnWriteArralyList没有使用synchronized锁,回答如下:

CopyOnWriteArrayListadd()方法不是使用synchronized关键字来实现的。实际上,CopyOnWriteArrayListadd()方法内部使用的是一种称为"写时复制"(Copy-on-Write)的技术。

在写时复制策略中,数据结构被修改时,修改操作会在一个新的副本上进行,而不是直接在原始数据上进行。这样,读取操作可以在原始数据上进行,而不需要等待写入操作完成。写入操作完成后,原始数据会被丢弃,新的副本会成为新的原始数据。

CopyOnWriteArrayList中,当调用add()方法时,它会创建一个新的数组副本,将新元素添加到该副本中,然后将原始数组引用指向新数组。由于创建新数组和修改操作是在一个单独的写锁上进行的,因此多个线程可以同时读取原始数组,而不会看到正在进行的写入操作。

因此,CopyOnWriteArrayListadd()方法并没有使用synchronized关键字来实现线程安全。而是使用写时复制技术和读写锁来实现更细粒度的并发控制。

因此,copyWriteArrayList在并发下是否效率更高有待商榷

Set不安全

package unsafe;import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;public class SetTest {public static void main(String[] args) {// Set<String> set = new HashSet<>(); // 线程不安全// Set<String> set = Collections.synchronizedSet(new HashSet<>());// 通过工具类将其转换成synchronized保证线程安全Set<String> set = new CopyOnWriteArraySet<>();// 通过读写复制策略保证线程安全for (int i = 1; i <= 20; i++) {new Thread(()->{set.add(UUID.randomUUID().toString().substring(0,5));System.out.println(set);},String.valueOf(i)).start();}}
}

hashSet的底层是什么?

HashSet本质上就是HashMap,源码:

/*** Constructs a new, empty set; the backing {@code HashMap} instance has* default initial capacity (16) and load factor (0.75).*/
public HashSet() {map = new HashMap<>();
}// add() set本质就是map key是无法重复的/*** Adds the specified element to this set if it is not already present.* More formally, adds the specified element {@code e} to this set if* this set contains no element {@code e2} such that* {@code Objects.equals(e, e2)}.* If this set already contains the element, the call leaves the set* unchanged and returns {@code false}.** @param e element to be added to this set* @return {@code true} if this set did not already contain the specified* element*/public boolean add(E e) {return map.put(e, PRESENT)==null;}
// PRESENT 是一个常量// Dummy value to associate with an Object in the backing Mapprivate static final Object PRESENT = new Object();

HashMap不安全

ConcurrentHashMap<>()

package unsafe;import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;public class MapTest {public static void main(String[] args) {// 线程不安全// map 是下面这条语句这样用的码?----> 不是,工作中不用HashMap// 默认等价于什么? -----> Map<String, String> map = new HashMap<>(16,0.75);// Map<String, String> map = new HashMap<>();// 线程安全Map<String,String> map = 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();}}
}

Callable

特点

1、可以有返回值

2、可以抛出异常

3、方法不同,run() / call()

package callable;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class CallableTest {public static void main(String[] args) throws ExecutionException, InterruptedException {// new Thread(new Runnable()).start();// 等价于 new Thread(new FutureTask<V>()).start();// new Thread(new FutureTask<V>(Callable)).start();--->FutureTask<V>的构造器为Callablenew Thread().start();// 怎么启动callableMyThread thread = new MyThread();FutureTask futureTask = new FutureTask(thread);// 适配类new Thread(futureTask,"A").start();new Thread(futureTask,"B").start();// 结果会被缓存,提高效率// 这个get方法可能会产生阻塞,加入call()是一个耗时操作,则get需要等待返回值// 一般将get放在最后,或者使用异步通信来处理Integer o = (Integer) futureTask.get();// 获取Callable的返回结果System.out.println(o);}
}class MyThread implements Callable<Integer> {@Overridepublic Integer call() throws Exception {System.out.println("call()");return 1024;}
}

细节:

1、 有缓存

2、结果可能需要等待,会阻塞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/106943.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS餐厅练习链接及答案

目录 链接&#xff1a; level 1 level 2 level 3 level 4 level 5 level 6 level 7 level 8 level 9 level 10 level 11 level 12 level 13 level 14 level 15 level 16 level 17 level 18 level 19 level 20 level 21 level 22 level 23 level 24 le…

第二证券:券商etf的买卖规则?

在当时迅速发展的证券商场中&#xff0c;ETF已经成为出资者的首选。ETF&#xff08;Exchange Traded Fund&#xff09;是一种证券东西&#xff0c;它被规划成类似于股票的生意办法。即出资者可以在证券生意所上以股票办法进行购买和出售。详细到券商ETF的生意规矩&#xff0c;咱…

【数据结构】双链表的相关操作(声明结构体成员、初始化、判空、增、删、查)

双链表 双链表的特点声明双链表的结构体成员双链表的初始化带头结点的双链表初始化不带头结点的双链表初始化调用双链表的初始化 双链表的判空带头结点的双链表判空不带头结点的双链表判空 双链表的插入&#xff08;按值插入&#xff09;头插法建立双链表带头结点的头插法每次调…

机器视觉在自动驾驶汽车中的应用与挑战

机器视觉在自动驾驶汽车中扮演着至关重要的角色&#xff0c;它使车辆能够感知和理解周围环境&#xff0c;以便自主驾驶。以下是机器视觉在自动驾驶汽车中的应用以及相关挑战&#xff1a; 应用&#xff1a; 障碍物检测与避让&#xff1a; 机器视觉系统可以检测和识别路上的障碍…

2023-10-16 itoa函数的局限以及实现

点击 <C 语言编程核心突破> 快速C语言入门 itoa函数的局限以及实现 前言一、功能描述二、具体实现对于第一版, 实现如下:第二版实现:测试用例: 总结 前言 把一个数用某种进制打印, 是一个很有用的功能, 值得庆幸的是, C语言有这么一个函数itoa(), 它可以把一个数转换为…

前端代码优化之从系统区分处理的业务场景看如何优化代码中的if判断

最近有个三端统一的技术场景&#xff0c;主要是以前移动端的 hybrid 网页在不考虑 UI 适配的情况下、期望能够直接在 PC 客户端投放。在评估修改面的时候发现了一段可以深思的代码&#xff1a; if (platform iphone) {location.href iphoneClientUrl; } else {location.href…

Webpack和JShaman相比有什么不同?

Webpack和JShaman相比有什么不同&#xff1f; Webpack的功能是打包&#xff0c;可以将多个JS文件打包成一个JS文件。 JShaman专门用于对JS代码混淆加密&#xff0c;目的是让JavaScript代码变的不可读、混淆功能逻辑、加密代码中的隐秘数据或字符&#xff0c;是用于代码保护的…

LED显示屏高刷新率和低刷新率有什么区别

LED显示屏的刷新率是指图像在LED显示屏上更新的速度&#xff0c;也即屏幕上的图像每秒钟出现的次数&#xff0c;它的单位是赫兹&#xff08;Hz&#xff09;。LED显示屏的刷新率越高&#xff0c;图像闪烁感就越小&#xff0c;稳定性也就越高&#xff0c;换言之对视力的保护也越好…

图片批处理工具 PhotoMill X直装 for mac

PhotoMill X是一款强大的图像处理软件&#xff0c;它可以帮助用户快速地对照片进行编辑、调整和转换。它支持在单个或批量模式下处理大量的图像文件&#xff0c;并具有直观的用户界面和易于使用的工具。 PhotoMill X具有的功能有&#xff1a; 裁剪、缩放、旋转、调整明暗度、…

python+django学生选课管理系统_wxjjv

1&#xff09;前台&#xff1a;首页、课程信息、校园论坛、校园公告、个人中心、后台管理。 &#xff08;2&#xff09;管理员&#xff1a;首页、个人中心、学生管理、教师管理课、程信息管理、课程分类管理、选课信息管理、作业信息管理、提交作业管理、学生成绩管理、校园论…

国际伦敦银点差费值得吗?

伦敦银是国际轨技术属市场上广受追捧的白银保证金交易品种&#xff0c;具有交易时长、交易制度灵活、资金利用率高等诸多的优点。 国际伦敦银的优势主要来自它所实行的是保证金交易制度。目前香港平台一般执行的保证金比例标准是2%&#xff0c;以目前22美元/盎司左右的白银价格…

epiiAdmin框架注意事项

1&#xff0c;epiiAdmin文档地址&#xff1a; 简介/安装 EpiiAdmin中文文档 看云 2&#xff0c;项目性想新建模块 composer.json文件——autoload选项——psr-4下增加模块名称&#xff0c;然后执行composer update命令。 "autoload": {"psr-4": {"…

代理现货白银有什么手续

成为现货白银代理商的好处有很多&#xff0c;一方面打理依然可以像普通投资者那样&#xff0c;采用平台的交易服务&#xff0c;直接在市场上通过交易&#xff0c;赚取高杠杆所带来的高回报&#xff0c;另一方面还可以根据自己客户的交易量&#xff0c;从平台获得一定的返佣&…

【剑指Offer】28.对称的二叉树

题目 给定一棵二叉树&#xff0c;判断其是否是自身的镜像&#xff08;即&#xff1a;是否对称&#xff09; 例如&#xff1a;下面这棵二叉树是对称的 下面这棵二叉树不对称。 数据范围&#xff1a;节点数满足 0≤n≤1000&#xff0c;节点上的值满足 0∣val∣≤1000 要求&am…

sql注入(5), sqlmap工具

sql注入, sqlmap工具 请注意&#xff0c;在实际操作中使用sqlmap测试和利用SQL注入等安全漏洞应始终符合法律法规和道德准则&#xff0c;并且需要在拥有明确授权的情况下进行。在没有获得适当授权的情况下对任何系统或网络进行渗透测试都是非法的。 sqlmap是由python开发的测…

C++引用(起别名)

0.引用的概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;从语法的角度来说编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。比如说你的名字和外号指的都是你本人。 void Test() {int a 10;int& ra …

【MAC】升级 Mac os 后报错

背景 17 年买的 mac&#xff0c;发现很多软件都无法安装&#xff0c;于是升级 mac os 到 10.13&#xff0c;从官网下载 10.13 版本&#xff0c;之后升级&#xff0c;升级还算顺利。但使用 git 的时候发现出现问题了。 问题 使用 git 出现如下错误 xcrun: error: invalid ac…

第二证券:市净率高好还是低好?

市净率是一个衡量公司股票投资价值的指标&#xff0c;通过比较公司股票价格和公司每股净资产的比值来评估公司股票的估值水平。市净率高好还是低好这个问题并没有一个简单的答案&#xff0c;取决于具体的市场环境和投资者的需求。本文将从多个角度分析市净率高好还是低好。 首…

头文件 <cstdarg> 的使用

进行函数可变参数的实现。 va_list&#xff1a; 适用于 va_start()、va_arg() 和 va_end() 这三个宏存储信息的类型。void va_start(va_list ap, last_arg)&#xff1a; 初始化 ap&#xff0c;其中 last_arg 是最后一个传递给函数的已知固定参数。type va_arg(va_list ap, typ…

How to install mysql 8.0 based on podman

创建配置目录 mkdir -p ~/data/podman/mysql-8.0/etc创建数据存储目录 mkdir -p ~/data/podman/mysql-8.0/var临时启动一个实例 docker run --detach \ --restart always \ --publish 23306:3306 \ --name mysql-8.0 \ --volume /usr/share/zoneinfo/Asia/Shanghai:/etc/lo…