Java8 遍历List 使用stream().parallel()并发安全

1. parallelStream是什么:

复制代码
 java 8引入了并行流的概念来进行并行处理,而并行流(Parallel Stream)利用所有可用CPU内核的优势,并行处理任务。其原理(Parallel Stream)是可以把大任务分成多个小任务执行, 最后再把执行结果进行合并, ForkJoinPool用工作窃取算法实现。

2.Java8的paralleStream是线程安全吗

复制代码
    一个简单例子,循环1000000次,往list中插入数据,最后看list的长度。
javascript 复制代码
public class TestParallel {
    public static void main(String[] args) {
        StopWatch stopWatch = new StopWatch();
        List<Integer> list = new ArrayList<>();
        stopWatch.start("TaskOneName");
        IntStream.range(0, 1000000).forEach(list::add);
        stopWatch.stop();
        System.out.println("list size:" + list.size());
        System.out.println("当前任务名称:" + stopWatch.currentTaskName() +" 执行时间:" + stopWatch.getTotalTimeMillis());
 
    }
}

执行时间以及list 中的size见下图

使用并发流

javascript 复制代码
public class TestParallel {
   public static void main(String[] args) {
       StopWatch stopWatch = new StopWatch();
       List<Integer> list = new ArrayList<>();
       stopWatch.start("TaskOneName");
       IntStream.range(0, 10000).parallel().forEach(list::add);
       stopWatch.stop();
       System.out.println("list size:" + list.size());
       System.out.println("当前任务名称:" + stopWatch.currentTaskName() +" 执行时间:" + stopWatch.getTotalTimeMillis());

   }
}

执行情况一:

执行情况二:

从上图可看出,list的add操作并非我们想要的结果。

3.如果非要用并行流怎么办

加锁吧。

javascript 复制代码
public class TestParallel {
    public static void main(String[] args) {
        StopWatch stopWatch = new StopWatch();
        List<Integer> list = new ArrayList<>();
        stopWatch.start("TaskOneName");
         Lock lock = new ReentrantLock();
        IntStream.range(0, 10000).parallel().forEach(adata->{
            lock.lock();
            try {
                list.add(adata);
            }finally {
                lock.unlock();
            }
        });
        stopWatch.stop();
        System.out.println("list size:" + list.size());
        System.out.println("当前任务名称:" + stopWatch.currentTaskName() +" 执行时间:" + stopWatch.getTotalTimeMillis());
 
    }
}

执行结果:

4.使用线程安全的ArrayList:

使用线程安全的ArrayList: CopyOnWriteArrayList

相关推荐
李少兄1 小时前
Windows 11 环境下 BAT 脚本无法执行的排查与修复指南
windows
xiangyun612 小时前
C++ list 模拟实现(二):const迭代器与反向迭代器,模板的黑魔法
开发语言·数据库·c++·算法·stl·list
解道Jdon2 小时前
FigCraft把Figma用Rust从零重写了一遍
ide·windows·git·svn·eclipse·github·visual studio
信奥卷王2 小时前
[GESP202509 六级] 划分字符串(含视频)
数据结构·算法
m0_752035632 小时前
Redis 数据结构总结
数据结构·数据库·redis
tachibana23 小时前
Go 语言的 Map 是否是并发安全的?
开发语言·数据结构·后端·golang·go·语言
Logic1013 小时前
C语言/数据结构字符串题解:统计“chhc“子串权值总和——一次遍历模式匹配
c语言·数据结构·算法·字符串·时间复杂度·空间复杂度·ascii
zh73144 小时前
Docker Desktop on Windows 挂载问题根因分析
windows·docker·容器
我命由我123454 小时前
LRU 缓存淘汰策略
数据结构·redis·学习·mysql·算法·缓存·学习方法
Surpass-HC4 小时前
WSL2 windows-ubuntu
linux·windows·ubuntu