一、ArrayList是线程不安全的,可以使用以下操作解决:

  1.使用相同功能的集合类替换,比如Vector集合是线程安全的,他们实现的接口都是一样的,但是Vector类是在jdk1.0出现的,不推荐使用

  

  2.使用 java.util.Collections类里面的静态方法synchronizedXXX(xxx),把不安全的集合当参数放进去。

  

  3.使用java.util.concurrent.CopyOnWriteArrayList或java.util.concurrent.CopyOnWriteArraySet

  

二、从上面第二个知道Map与Set都是线程不安全的,其中Map的第三个解决方法是 java.util.concurrent.ConcurrentHashMap

三、代码实现

  

package com.jenne.mydemo;

import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet; public class TestCollection {
@Test
public void testList() {
/* //可能会出现java.util.ConcurrentModificationException
List<String> list = new ArrayList<>();
for (int i = 1; i <= 8; i++) {
new Thread(() -> {
list.add(Thread.currentThread().getName()+"--->测试");
System.out.println(list);
}).start();
}*/ /*List<String> list = new Vector<>();//不推荐
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
list.add(Thread.currentThread().getName()+"--->测试");
System.out.println(list);
}).start();
}*/ /*List<String> list = Collections.synchronizedList(new ArrayList<>());//不推荐
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
list.add(Thread.currentThread().getName()+"--->测试");
System.out.println(list);
}).start();
}*/ List<String> list = new CopyOnWriteArrayList<>();//推荐使用
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
list.add(Thread.currentThread().getName() + "--->测试");
System.out.println(list);
}).start();
}
} @Test
public void testSet() {
/*//java.util.ConcurrentModificationException
Set<String> set = new HashSet<>();
for (int i = 1; i <= 16; i++) {
new Thread(() -> {
set.add(Thread.currentThread().getName()+"--->测试");
System.out.println(set);
}).start();
}*/ /* Set<String> set = Collections.synchronizedSet(new HashSet<>());//不推荐
for (int i = 1; i <= 16; i++) {
new Thread(() -> {
set.add(Thread.currentThread().getName()+"--->测试");
System.out.println(set);
}).start();
}*/ Set<String> set = new CopyOnWriteArraySet<>();//推荐使用
for (int i = 1; i <= 16; i++) {
new Thread(() -> {
set.add(Thread.currentThread().getName() + "--->测试");
System.out.println(set);
}).start();
}
} @Test
public void testMap() {
/*//java.util.ConcurrentModificationException
Map<String,String> map = new HashMap<>();
for (int i = 1; i <= 16; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(),"--->测试");
System.out.println(map);
}).start();
}*/ /*Map<String, String> map = Collections.synchronizedMap(new HashMap<>());//不推荐
for (int i = 1; i <= 16; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(), "--->测试");
System.out.println(map);
}).start();
}*/ Map<String,String> map = new ConcurrentHashMap<>();//推荐使用
for (int i = 1; i <= 16; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(),"--->测试");
System.out.println(map);
}).start();
} }
}

JUC---07解决集合线程不安全的更多相关文章

  1. 解决ArrayList线程不安全

    前些天做项目时,程序出现意外的问题,经后来分析是使用ArrayList这个线程不安全的方法导致 解决这个问题通常有两种方法(个人认为) 一:使用synchronized关键字,这个大家应该都很熟悉了, ...

  2. android 解决子线程进行UI操作

    Android确实不允许在子线程中进行UI操作的,但我们有时必须在子线程里去执行一些耗时的任务,然后根据任务的执行结果来更新相应的UI控件. Android提供了一套异步消息处理机制,可以解决子线程中 ...

  3. JUC源码分析-线程池篇(三)ScheduledThreadPoolExecutor

    JUC源码分析-线程池篇(三)ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor.它主要用来在 ...

  4. JUC源码分析-线程池篇(二)FutureTask

    JUC源码分析-线程池篇(二)FutureTask JDK5 之后提供了 Callable 和 Future 接口,通过它们就可以在任务执行完毕之后得到任务的执行结果.本文从源代码角度分析下具体的实现 ...

  5. JUC源码分析-线程池篇(三)Timer

    JUC源码分析-线程池篇(三)Timer Timer 是 java.util 包提供的一个定时任务调度器,在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次. 1. Ti ...

  6. JUC源码分析-线程池篇(一):ThreadPoolExecutor

    JUC源码分析-线程池篇(一):ThreadPoolExecutor Java 中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池 ...

  7. Java 集合 线程安全

    Java中常用的集合框架中的实现类HashSet.TreeSet.ArrayList.ArrayDeque.LinkedList.HashMap.TreeMap都是线程不安全的,如果多个线程同时访问它 ...

  8. List 集合线程安全测试

    最近在做一些代码整理工作,涉及到List 线程安全问题,查了一些资料.网上有些资料说List 增减成员(Add , Remove) 是安全的,但不保证成员属性值访问安全性,及禁止对 List 跨线程遍 ...

  9. 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~ 线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析

    看两个例子,一个是在一个进程里设置另外一个进程中控件的属性.另外一个是在一个进程里获取另外一个进程中控件的属性. 第一个例子 最近,在做一个使用线程控制下载文件的小程序(使用进度条控件显示下载进度)时 ...

随机推荐

  1. PYG2010-02-精装友情通讯录再分析

  2. SSH 框架常见错误

    新手学习SSH框架的时候总会遇到很多问题,一碰到404 或者500错误就不知道怎么解决. 404错误是很常见的一个错误,如果没有用框架基本上只可能是没有这个路径或者文件,但是用了框架之后404的原因就 ...

  3. 提效工具-python解析xmind文件及xmind用例统计

    现状 每个公司都有一个维护测试case的系统,有自研的也有买的,比如QC, 禅道等等,QA往往习惯使用xmind等思维导图工具来编写测试用例,因为思路清晰,编写方便,那么这就有一个问题,大多公司要求所 ...

  4. (转)Java中的值传递和引用传递

    Java中的值传递和引用传递 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?     答:是值传递.Java 编程语言只有值 ...

  5. Linux里面的压缩和解压类指令

    gzip/gunzip 指令 ( .gz  不能压缩目录) gzip 用于压缩文件, gunzip 用于解压的 . gzip gzip命令用来压缩文件.gzip是个使用广泛的压缩程序,文件经它压缩过后 ...

  6. python_多级菜单_纯循环与分支

    源代码: #!/usr/bin/python3 __author__ = 'beimenchuixue' __blog__ = 'http://www.cnblogs.com/2bjiujiu/' d ...

  7. 注册表“CLSID”下面的“InprocServer32”子键是什么?

    这个键值有什么用?每个CLSID下基本都有,即使没有其它项也会有此项.谁能详细说下,"InprocServer32"子键起什么作用?谢了. 刚好遇到这问题了,这是我找到的:Inpr ...

  8. helm部署mysql

    如果您的kubernetes已有了helm,那么部署mysql的步骤可以进一步简化,那些原先需要自己动手配置的deployment和service都已集成在chart中,今天就来实战通过helm部署m ...

  9. Morris遍历

    Morris遍历 一种遍历二叉树的方式,并且时间复杂度O(N),额外空间复杂度O(1) 通过利用原树中大量空闲指针的方式,达到节省空间的目的 Morris遍历可以改前中后序的树遍历 思路: 创建一个当 ...

  10. IO那些事

    IO(Input\Output): 即输入输出,通常指数据在存储器(内部和外部)或其他周边设备之间的输入和输出,是信息处理系统(例如计算机)与外部世界(可能是人类或另一信息处理系统)之间的通信.说的简 ...