Java多线程并发编程学习笔记【JUC包相关类】

1、AtomicInteger、AtomicLong、AtomicBoolean等等

这几个类可以实现多线程之间的原子性递增或递减或取值操作,原理一个实例拥有一个原子变量,然后进行CAS操作。

2、LongAdder

然而AtomicLong等类存在一个主要问题就是,在高并发下大量线程会同时去竞争更新同一个原子变量,但由于同时只有一个线程的CAS操作会成功,导致其他线程竞争失败后,会无限循环地进行自旋尝试CAS操作,造成CPU资源的浪费。因此JDK8新增了一个原子性递增或者递减的LongAdder类,来克服AtomicLong上述缺点。解决的思路是尽量让一个线程拥有一个原子变量,这样就不用竞争了。

LongAdder类add()方法思路大致如下

1、用Cells数组存储2的N次方个原子变量(每个变量称为cell),然后让线程更具自己的“threadLocalRandomProbe”变量值去获取其中的元素,尽量每个线程都能获取到空的数组元素,为此在每次进行元素的cas操作失败的时候,会进行获取cell的优化处理;

2、获取到cell后,会进行CAS操作,假如失败会再尝试一次,还是失败就会进行cells扩容,每次扩容为上一次的两倍(左移操作),当cells数组个数大于可用的处理器个数时便不再扩容;然后再去获取cell,直到CAS操作成功

也就是说LongAdder利用cpu能同时处理的最大线程数,加快了CAS操作速度,而且每个线程都存储着自己获取cell的方式。

3、LongAccumulator

LongAdder 类是LongAccumulator 的一个特例, LongAccumul ator 比LongAdder 的功能更强大。例如下面的构造函数, 其中accumulatorFunction 是一个双目运算器接口, 其根据输入的两个参数返回一个计算值, identity 则是LongAccumulator 累加器的初始值。

public LongAccumulator (LongBinaryOperator accumulator Function ,long identity ) {
this.function = accumulatorFunction ;
base = this.identity= identity;
public interface LongBinaryOperator {
//根据两个参数计算并返回一个值
long applyAsLong ( long left , long right ) ;
}

上面提到, LongAdder 其实是LongAccumulator 的一个特例, 调用LongAdder 就相当于使用下面的方式调用LongAccumulator :

LongAdder adder= new LongAdder () ;
LongAccumulator accumulator= new LongAccumulator(new LongBinaryOperator() {
@Override
public long applyAsLong(long left , long right ) {
return left + right ;
}
},0);

4、CopyOnWirteArrayList

并发包中的List只有CopyOnwirteArrayList,此类是线程安全的ArrayList,但其存在弱一致性。所谓弱一致性就是说数据更新后,后续的访问只能访问到部分或者全部访问不到。

其原理大致为:

1、利用volatile修饰array数组,进行增删改操作时,用ReentrantLock获取lock再操作

之所以存在弱一致性,因为在使用iterator()遍历时,原数组已经修改了,但如果在修改前便已经获取了其iterator,iterator包含数组的final修饰的复制版本,后面数据修改并不会同步到复制版本,导致后面进行遍历时,仍然是修改前的数据。

所以应该等线程跑完了,再获取iterator。

----------------------------------------以下更新于2021年7月21日 06:49:07-----------------------------------------

1、ThreadLocalRandom类,让每个线程都持有一个本地的种子变量,该种子变量只有在使用随机数时才会被 初始化

ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
int random = threadLocalRandom.nextInt();

在多线程 下使用单个Random 实例生成随机数时,当多个线程同时计算随机数来计算新的种子 时, 多个线程会竞争同一个原子变量的更新操作,由于原子变量的更新是CAS 操作,同 时只有一个线程会成功,所以会造成大量线程进行自旋重试, 这会降低并发性能,所以 ThreadLocalRandom 应运而生。

PS:Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。

2、AtomicInteger、AtomicLong:递增、递减操作,原理是使用CAS提供非阻塞原子性操作,竞争获取原子变量。java 8 后新增LongAdder类,原理是将原子变量分成多个,再合并。

LongAdder是LongAccumulator的特例,LongAccumulator提供更强大的自定义累加规则

3、AtomicBoolean,布尔型的线程安全类。boolean线程不安全,boolean其实包含了boolean.false和boolean.true两个对象。AtomicBoolean将boolean型的true、false转成1和0,再使用CAS方法提供非阻塞原子性操作

4、SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。

注意线程安全,使用DateUtils。亦推荐如下处理:

private static final ThreadLocal df = new ThreadLocal() {

@Override

protected DateFormat initialValue() {

return new SimpleDateFormat("yyyy-MM-dd");

}

};

说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe。

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值