使用多个线程访问列表

时间:2015-04-30 07:49:17

标签: java multithreading

java.lang.NullPointerException函数线程是否安全?多个线程会在列表上正确循环吗?

compute()

6 个答案:

答案 0 :(得分:1)

考虑到数据没有变异(正如你在评论中提到的那样),不会有任何脏/幻读。

答案 1 :(得分:1)

如果列表是专门为该方法创建的,那么您就可以了。也就是说,如果任何其他方法或类中的列表未被修改,那么该代码是线程安全的,因为您只是在阅读。< / p>

如果您不确定参数是否来自可信赖的来源(即使您确定),则一般建议是制作该集合的只读副本。

this.list = Collections.unmodifiableList(new ArrayList<Integer>(list));

但请注意,列表元素也必须是线程安全的。如果在您的实际场景中,列表包含一些可变结构,而不是 Integer (它们是不可变的),您应该确保对元素的任何修改都是线程安全的。

答案 2 :(得分:0)

此版本

class Foo {
    private final List<Integer> list;

    public Foo(List<Integer> list) {
        this.list = new ArrayList<>(list);
    }

    public void compute() {
        for(Integer i: list) {
             // ...
        }
    }
}

线程安全的,如果以下成立:

  1. list arc to ctor无法在ctor运行时修改(例如,它是调用者中的局部变量)或线程安全本身(例如CopyOnWriteArrayList);
  2. compute无法修改list内容(正如OP所述)。我猜compute应该不是void,而是返回一些数值,是任何效用......

答案 3 :(得分:0)

cocncurent library中有线程安全列表。如果您想要线程安全的集合,请始终使用它。线程安全列表为 CopyOnWriteArrayList

答案 4 :(得分:0)

如果您可以保证列表在其他地方没有被修改,而您正在迭代该代码是线程安全的。

我会创建一个列表的只读副本,但绝对确定它不会在别处修改:

class Foo {

    private List<Integer> list;

    public Foo(List<Integer> list) {
        this.list = Collections.unmodifiableList(new ArrayList<>(list));
    }

    public void compute() {
        for (Integer i: list) {
            // do some thing with it 
            // NO LIST modifications 
        }
    }
}

如果您不介意为项目添加依赖项,我建议您使用Guava&#39; ImmutableList

        this.list = ImmutableList.copyOf(list);

使用Guavas不可变集合也是一个好主意,只要您使用的集合不会发生变化,因为它们本身就是不可变的线程安全。

答案 5 :(得分:0)

例如,在拥有2个线程时,您可以轻松检查行为:

public class Test {

    public static void main(String[] args) {
        Runnable task1 = () -> { new Foo().compute(); };
        Runnable task2 = () -> { new Foo().compute(); };
        new Thread(task1).start();
        new Thread(task2).start();
    }

}

如果保证列表不会在其他任何地方更改,则迭代它是线程安全的,如果您实现compute只是打印列表内容,调试代码应该有助于您理解它是< / em>线程安全。