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 ...
随机推荐
- ES6学习 第五章 正则的扩展
前言 本章介绍正则的扩展.有些不常用的知识了解即可. 本章原文链接:正则的扩展 RegExp 构造函数 从 ES6 开始,如果RegExp构造函数第一个参数是一个正则对象,并且第二个标志存在且为标志参 ...
- 洛谷 P4663 - [BalticOI 2008]魔法石(dp)
题面传送门 A:我该是有多无聊来写这种题的题解啊 B:大概是因为这题题解区里没有题解所以我来写一篇了,说明我有高尚的济世情怀(大雾 跑题了跑题了 首先看到字典序第 \(i\) 小小可以自然地想到按位决 ...
- Python基础之列表内置方法
目录 1. 列表 1.1 序列 1.2 通用的序列操作 1.3 列表的基本操作 1.4 列表方法 1. 列表 数据结构:以某种方式(如通过编号)组合起来的元素(如数,字符乃至其他数据结构)集合. 在p ...
- Label -- 跳出循环的思路
let num = 0 ; outPoint: //label for (let i = 0; i < 10; i++) { for ( let j = 0; j < 10; j++) { ...
- 日常Java 2021/10/19
Java集合框架 Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射. Collection接口又有3种子类型,Li ...
- The Ultimate Guide to Buying A New Camera
[photographyconcentrate] 六级/考研单词: embark, thrill, excite, intimidate, accessory, comprehensive, timi ...
- day31 协程
day31 协程 一.死锁与递归锁 所谓死锁:是指两个或者两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产 ...
- KMP算法思路
题目 给定一个字符串\(S\),求\(M\)字符串是否是\(S\)字符串中的子串.如果是,返回\(M\)对应\(S\)的第一个下标,否则返回-1. 例如:S串为a b c d a b c d a b ...
- [php代码审计] 通读审计之shangfancms
前言 大部分的MVC框架,访问的控制器大部分是由外部参数来决定的,那么本篇文章所通读的MVC框架与之前的一系列MVC框架不太一样,它的路由是由程序本身的路由表来决定的. 源码下载 https://ww ...
- python 从ubantu环境迁移到windows环境
下载安装Anaconda3 Anaconda3-2021.05-Windows-x86_64.exe 默认安装目录 C:\ProgramData\Anaconda3 可以启动Anaconda查看不同的 ...