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 ...
随机推荐
- 不用Spring Boot的痛苦是什么?用了Spring Boot以后的好处是什么?
1.不用Spring Boot的痛苦是什么? (1)各种技术整合在一起,版本混乱,大量依赖自己去找,依赖冲突 (2)基于xml格式的配置文件,对各种技术框架进行大量的繁琐配置,mvc-servlet. ...
- IE 跨域设置
开发的时候会发现IE下跨域无法访问,报错: Failed to load resource: net::ERR_CONNECTION_REFUSED 解决方法有两种: 自己写代理服务,访问代理服务,代 ...
- Python画一个四点连线并计算首尾距离
import turtle import math #先定义4个坐标 x1,y1=100,100 x2,y2=100,-100 x3,y3=-100,-100 x4,y4=-100,100 #然后 ...
- Jenkins系列-权限管理
在实际工作中,存在多个团队都需要Jenkins来实现持续交付,但是又希望不同团队之间进行隔离,每个项目有自己的view, 只能看到自己项目的jenkins job. 但是,jenkins默认的权限管理 ...
- BehaviorTree.CPP行为树BT的装饰器节点(五)
Decorators 装饰器是只能有一个子项的节点. 由装饰者来决定是否,何时以及对子节点进行tick. InverterNode tick子节点一次,如果子节点失败则返回SUCCESS,如果孩子成功 ...
- 在Ubuntu上安装Docker Engine
在Ubuntu上安装Docker Engine 这篇文章是介绍如何在在Ubuntu上安装Docker Engine,就是Google翻译官方文档的版本,英语好的直接官方原文.原文 要在Ubuntu上开 ...
- Congratulations, FYMS-OIers!
Fuzhou Yan'an Middle School Online Judge 又一次上线啦! 真的是一波三折,主要功劳必须得属于精通网页编排.ubuntu 下如何使用 rm -rf 语句但是又能够 ...
- Docker-Mysql-proxy Mysql Proxy实现读写分离
Docker-Mysql-proxy Mysql实现读写分离与负载 原理 MySQL Proxy处于客户端应用程序和MySQL服务器之间,通过截断.改变并转发客户端和后端数据库之间的通信来实现其功 ...
- 蛋白质组DIA深度学习之谱图预测
目录 1. 简介 2. 近几年发表的主要工具 1.DeepRT 2.Prosit 3. DIANN 4.DeepDIA 1. 简介 基于串联质谱的蛋白质组学大部分是依赖于数据库(database se ...
- Python—python2.7.5升级到2.7.14或者直接升级到3.6.4
python2.7.5升级到2.7.14 1.安装升级GCC yum install -y gcc* openssl openssl-devel ncurses-devel.x86_64 bzip2 ...