并行流parallelStream

parallelStream是JDK8引入的特性,用于并行执行流操作,通过ForkJoinPool实现。forEachOrdered保证顺序但可能损失效率,而forEach可能导致后续代码不等待其完成。使用时注意线程安全,如需添加操作应使用线程安全集合。parallelStream不能直接传递threadLocal值,但可以借助TransmittableThreadLocal并配置VM参数。
摘要由CSDN通过智能技术生成

parallelStream是jdk8引入的特性,其实就是一个并行执行的流,它通过默认的ForkJoinPool,底层是窃取算法,利用了现代硬件设备多核,可能提高你的多线程任务的速度。

1.两种写法都行:stream().parallel()或者parallelStream()。

2.numbers.parallelStream().forEach会打乱顺序,如果想要案顺序处理,要用numbers.parallelStream().forEachOrdered,但forEachOrdered可能会失去平行化的一些优势。

3.用法例子:

For1:

List<AbcDto> results = refers.parallelStream().map(t -> {
    AbcDto dto = AbcDto.builder()
            ....
            .build();

    doFormat(t, dto);
    return dto;
}).collect(Collectors.toList());

4.并行流要注意的坑:

坑1:

parallelStream的后面如果是foreach,且foreach后面还有代码,则就会并不等待parallelStream执行完就跑了后面的代码,应该改为map或filter处理【但parallelStream当前主线程也会做为线程池一员去执行foreach中逻辑的,理论上不会出现这种情况的!】。

示例:

List<CommentMngDto> records = new ArrayList<>(pageableInfo.getRecords().size());

        PageableInfo<CommentMngDto> result = new PageableInfo<>(pageableInfo.getPageNum(), pageableInfo.getPageSize(), pageableInfo.getTotal(), records);

        pageableInfo.getRecords().parallelStream().forEach(com -> {

            CommentMngDto dto = new CommentMngDto();

            dto.fromComment(com, assetService);

            Organization org = organizationService.getOrgByCode(com.getOrgCode());

            Optional.ofNullable(org).ifPresent(o -> dto.setOrgName(I18nUtil.getMultiLang(o.getNameMultil(), null)));

            records.add(dto);

        });

        return result;

问题:返回的records数据少了。

最终换成:

List<CommentMngDto> records = pageableInfo.getRecords().parallelStream().map(com -> {

            CommentMngDto dto = new CommentMngDto();

            dto.fromComment(com, assetService);

            Organization org = organizationService.getOrgByCode(com.getOrgCode());

            Optional.ofNullable(org).ifPresent(o -> dto.setOrgName(I18nUtil.getMultiLang(o.getNameMultil(), null)));

            return dto;

        }).sorted(Comparator.comparing(CommentMngDto::getCreateTime).reversed()).collect(Collectors.toList());

        PageableInfo<CommentMngDto> result = new PageableInfo<>(pageableInfo.getPageNum(), pageableInfo.getPageSize(), pageableInfo.getTotal(), records);

        return result;

坑2:就是parallelStream中处理逻辑代码,如果涉及到一些集合类的add等操作的,要用线程安全的集合类,如CopyOnWriteArrayList、ConcurrentHashMap等。

所以,可见,坑1是不存在的,坑1中出现问题的根源是坑2,所以,还是可以在parallelStream放心使用forEach的。

坑3:parallelStream无法传递threadLocal的值。

有些人说,我用TransmittableThreadLocal不行吗? 不行,还真不行。

如何解决,使用TransmittableThreadLocal,并且,

在启动的VM参数加上:

-javaagent:D:/programfiles/apache-maven-3.6.3/m2/myrepository/com/alibaba/transmittable-thread-local/2.12.2/transmittable-thread-local-2.12.2.jar

当然,如果想控制并发数,还可以加上:

-Djava.util.concurrent.ForkJoinPool.common.parallelism=16

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值