MST

星途 面试题库

面试题:Java中Stream foreach方法在处理集合时如何避免线程安全问题

假设有一个ArrayList<String>,在使用Java Stream的foreach方法对其进行遍历并修改元素时,可能会出现线程安全问题。请阐述如何避免这种问题,并且给出示例代码。
49.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 避免问题的方法
    • 使用同步集合:将ArrayList转换为同步集合,如Collections.synchronizedList,这样在多线程环境下对集合的操作会被同步。
    • 使用线程安全的集合:例如CopyOnWriteArrayList,它在修改操作时会创建一个新的底层数组,读操作基于旧数组,从而实现读写分离,保证线程安全。
    • 使用并行流时的同步机制:如果使用并行流,需要使用Atomic类型或同步块来确保对元素的修改是线程安全的。
  2. 示例代码
    • 使用同步集合
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class SynchronizedListExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");

        List<String> synchronizedList = Collections.synchronizedList(list);
        synchronizedList.stream()
              .map(String::toUpperCase)
              .collect(Collectors.toList());
    }
}
  • 使用线程安全的集合(CopyOnWriteArrayList)
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

public class CopyOnWriteArrayListExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");

        List<String> copyOnWriteList = new CopyOnWriteArrayList<>(list);
        copyOnWriteList.stream()
              .map(String::toUpperCase)
              .collect(Collectors.toList());
    }
}
  • 使用并行流时的同步机制(以Atomic类型为例)
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class ParallelStreamSyncExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");

        AtomicInteger index = new AtomicInteger(0);
        List<String> result = list.parallelStream()
              .map(s -> {
                    int i = index.getAndIncrement();
                    // 这里可以进行基于索引的同步操作
                    return s.toUpperCase();
                })
              .collect(Collectors.toList());
    }
}