java 多线程 集合的包装方法Collections.synchronizedXXXXX;线程安全的集合类:Java.util.concurrent.ConcurrentXXX;java.util.concurrent.CopyOnWriteXXXX
问题:ArrayList 等线程不安全
当多线程并发修改一个集合数据时,可能同一个下标位置被覆盖。
示例代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeUnit; /**
* @ClassName ForkJoinPoolArrayListNotSafe
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/28.
*/
public class ForkJoinPoolArrayListNotSafe {
public static void main(String[] args) throws InterruptedException {
/**
* 存放数据的集合
*/
List<Integer> nums = new ArrayList<>();
/**
* 随机数类
*/
Random random = new Random();
/**
* 线程池
*/
ForkJoinPool forkJoinPool = new ForkJoinPool();
/**
* 线程池提交任务类
*/
for (int j=0; j<10; j++){
forkJoinPool.submit(new RecursiveAction() {
@Override
protected void compute() {
for (int i=0; i<1000; i++){
nums.add(random.nextInt());
}
}
});
System.out.println((j+1) + "千次提交");
}
/**
* 等待执行结束
*/
forkJoinPool.awaitTermination(2, TimeUnit.SECONDS);
/**
* 关闭提交入口
*/
forkJoinPool.shutdown();
/**
* 查看执行结果
*/
System.out.println("计算结果:num.size():" + nums.size());
}
}
1、非线程安全集合~转~线程安全包装方法:Collections.synchronizedXXXXX(非线程安全集合)
将非线程安全集合转为线程安全集合(底层实现逻辑:synchronized 效果变为串行)Collctions提供了如下几个静态方法
- static <T> Collection<T> synchronizedCollection(Collection<T> c): 通过c返回一个线程安全的Collection
- static <T> List synchronizedList(List<T> list):通过List返回一个线程安全的List
- static <K,V> Map<K,V> synchronizedMap(Map<K,V> map):通过map返回一个线程安全的map
- static <T> Set<T> synchronizedSet(Set set): 通过set返回一个线程安全的set
- static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> sortedMap): 通过sortedMap返回一个线程安全的SortedMap
- static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> sortedSet): 通过SortedSet返回一个线程安全的SortedSet
如上示例代码包装后:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeUnit; /**
* @ClassName ForkJoinPoolArrayListSynchornized
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/28.
*/
public class ForkJoinPoolArrayListSynchornized {
public static void main(String[] args) throws InterruptedException {
/**
* 集合包装类包装线程不安全集合
*/
List<Integer> nums = Collections.synchronizedList(new ArrayList<>());
Random random = new Random();
ForkJoinPool forkJoinPool = new ForkJoinPool();
/**
* 提交多线程任务向集合添加1万个元素
*/
for (int j=0; j<10; j++){
for (int i=0; i<1000; i++){
forkJoinPool.submit(new RecursiveAction() {
@Override
protected void compute() {
nums.add(random.nextInt());
}
});
}
}
/**
* 等待执行结果
*/
forkJoinPool.awaitTermination(1, TimeUnit.SECONDS);
forkJoinPool.shutdown();
System.out.println("num.size():" + nums.size());
}
}
2、线程安全的集合(Java.util.concurrent包下)
- ConcurrentLinkedQueue
- ConcurrentHashMap
3、CopyOnWrite集合的介绍:
如上示例用CopyOnWriteArrayList代替
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeUnit; /**
* @ClassName ForkJoinPoolArrayListSynchornized
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/28.
*/
public class ForkJoinPoolCopyOnWriteArrayList {
public static void main(String[] args) throws InterruptedException {
/**
* 集合包装类包装线程不安全集合
*/
List<Integer> nums = new CopyOnWriteArrayList<>();
Random random = new Random();
ForkJoinPool forkJoinPool = new ForkJoinPool();
/**
* 提交多线程任务向集合添加1万个元素
*/
for (int j=0; j<10; j++){
for (int i=0; i<1000; i++){
forkJoinPool.submit(new RecursiveAction() {
@Override
protected void compute() {
nums.add(random.nextInt());
}
});
}
}
/**
* 等待执行结果
*/
forkJoinPool.awaitTermination(1, TimeUnit.SECONDS);
forkJoinPool.shutdown();
System.out.println("num.size():" + nums.size());
}
}
测试ConcurrentHashMap:
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeUnit; /**
* @ClassName ForkJoinPoolConcurrentHashMapTest
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/28.
*/
public class ForkJoinPoolConcurrentHashMapTest {
public static void main(String[] args) throws InterruptedException {
Map<String,Integer> persons = new ConcurrentHashMap<>();
ForkJoinPool pool = new ForkJoinPool();
Random random = new Random();
for (int i=0; i<10; i++){
for (int j=0; j<1000; j++) {
pool.submit(new RecursiveAction() {
@Override
protected void compute() {
persons.put("random:" + random.nextInt(), random.nextInt());
}
});
}
}
pool.awaitTermination(15, TimeUnit.MILLISECONDS);
persons.forEach((k,v) -> System.out.println(k + "=" +v));
pool.shutdown();
System.out.println("persons.size:" + persons.size());
}
}
java 多线程 集合的包装方法Collections.synchronizedXXXXX;线程安全的集合类:Java.util.concurrent.ConcurrentXXX;java.util.concurrent.CopyOnWriteXXXX的更多相关文章
- “全栈2019”Java多线程第十二章:后台线程setDaemon()方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java 多线程基础(十)interrupt()和线程终止方式
Java 多线程基础(十)interrupt()和线程终止方式 一.interrupt() 介绍 interrupt() 定义在 Thread 类中,作用是中断本线程. 本线程中断自己是被允许的:其它 ...
- “全栈2019”Java多线程第二十二章:饥饿线程(Starvation)详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- 最全java多线程总结3——了解阻塞队列和线程安全集合不
看了前两篇你肯定已经理解了 java 并发编程的低层构建.然而,在实际编程中,应该经可能的远离低层结构,毕竟太底层的东西用起来是比较容易出错的,特别是并发编程,既难以调试,也难以发现问题,我们还是 ...
- java多线程中用到的方法详细解析
在多线程学习的过程中涉及的方法和接口特别多,本文就详细讲解下经常使用方法的作用和使用场景. 1.sleep()方法. 当线程对象调用sleep(time)方法后,当前线程会等待指定的时间(t ...
- 【JAVA多线程中使用的方法】
一.sleep和wait的区别. 1.wait可以指定时间,也可以不指定. 而sleep必须制定. 2.在同步的时候,对于CPU的执行权和以及锁的处理不同. wait:释放执行权,释放锁. sleep ...
- Java多线程中的join()方法
一.join()方法介绍 join() 定义在Thread.java中.join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的join( ...
- java 多线程中的wait方法的详解
java多线程中的实现方式存在两种: 方式一:使用继承方式 例如: PersonTest extends Thread{ String name; public PersonTest(String n ...
- java 多线程——join()方法
在java语言中,join()方法的作用是让调用该方法的线程在执行完run()方法后,再执行join 方法后面的代码. 简单点说就是,将两个线程合并,用于实现同步的功能. 具体而言:可以通过线程A的j ...
随机推荐
- [APIO2020]有趣的旅途
注意到第一个点是可以钦定的. 那么我们考虑在重心的子树里反复横跳. 每次选择不同子树里的深度最大的点. 在同一颗子树里可能会在lca处出现问题. 那么我们选择重心,要考虑到会不会出现一颗子树不够选的操 ...
- Codeforces 1466G - Song of the Sirens(哈希)
Codeforces 题面传送门 & 洛谷题面传送门 事实证明,有的难度评分不算很高.涉及的知识点不算很难的题目也能出得非常神仙 首先考虑如何暴力求答案.注意到一个文本串 \(T\) 在 \( ...
- Atcoder Beginner Contest 164 E Two Currencies(拆点+最短路)
题目链接 题意:有 \(n\) 个城市,它们由 \(m\) 条双向道路连接,保证它们能够彼此到达.第 \(i\) 条道路连接 \(u_i,v_i\),需要花费 \(x_i\) 个银币,耗费 \(t_i ...
- 洛谷 P5469 - [NOI2019] 机器人(区间 dp+拉格朗日插值)
洛谷题面传送门 神仙题,放在 D1T2 可能略难了一点( 首先显然对于 P 型机器人而言,将它放在 \(i\) 之后它会走到左边第一个严格 \(>a_i\) 的位置,对于 Q 型机器人而言,将它 ...
- UVA12267 Telephone Network
UVA12267 Telephone Network nb tea. 注意到如果两个需要相互接通的请求 \(a,b\) 在某一层分别接了上下两个开关,那么接下来它们永远也无法接通了,因为上下两个开关是 ...
- Python序列化,json&pickle&shelve模块
1. 序列化说明 序列化可将非字符串的数据类型的数据进行存档,如字典.列表甚至是函数等等 反序列化,将通过序列化保存的文件内容反序列化即可得到数据原本的样子,可直接使用 2. Python中常用的序列 ...
- Redis | 第9章 Lua 脚本与排序《Redis设计与实现》
目录 前言 1. Lua 脚本 1.1 Redis 创建并修改 Lua 环境的步骤 1.2 Lua 环境协作组件 1.3 EVAL 命令的实现 1.4 EVALSHA 命令的实现 1.5 脚本管理命令 ...
- EDA简介
Electronic design automation (EDA), also referred to as electronic computer-aided design (ECAD),[1] ...
- HTML5 之 FileReader 的使用 (二) (网页上图片拖拽并且预显示可在这里学到) [转载]
转载至 : http://www.360doc.com/content/14/0214/18/1457948_352511645.shtml FileReader 资料(英文): https://de ...
- 【STM32】使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡
由于一张SD卡要能读写,涉及到的技术有些多,我打算分以下几篇博客 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡 [STM32]使用SDIO进行SD卡读写,包含 ...