代码之家  ›  专栏  ›  技术社区  ›  marionmaiden

带列表的线程

  •  0
  • marionmaiden  · 技术社区  · 14 年前

    类型X的对象列表 每个对象X都有一个非常大的整数列表

    我有一个静态方法(称为getSubsetOfX),它接收 对象X 对象X的整数列表 返回的列表是X中包含的所有整数的子集。

    对于列表中包含的每个X调用此方法。然后我将返回的列表插入整数列表的列表中。

    这是我在紧凑版中解释的代码:

    // Class of object X
    public class X{
        public List<Integer> listX;
        ...
    }
    
    // Utility class
    public class Util{
        // Return a sub-set of Integer contained in X
        public static List<Integer> getSubsetOfX(X x){...}
    }
    
    
    public class exec{
        public static void main(String args[]){
            // Let's suppose that lx is already filled with data!
            List<X> lx = new ArrayList<X>();
    
            // List of the subsets of integer
            List<List<Integer>> li = new ArrayList<ArrayList<Integer>>();
    
            for(X x : lx){
                // I want to turn this step "threadrized"
                li.add(getSubsetOfX(x));
            }
        }
    }
    

    我不知道列表是否允许并发插入。我也不知道如何在里面应用线程。我读了一些关于线程的文章,但是,由于run()方法不返回任何内容,如何打开该方法 getSubsetOfX(X X)

    你能帮我做这个吗?

    2 回复  |  直到 14 年前
        1
  •  3
  •   David Z    14 年前

    说清楚点, getSubsetOfX()

    Executor s。第一步是创建一个 Callable 那就跑 getSubsetOfX(x) 在一个给定的 X . 像这样:

    public class SubsetCallable implements Callable<List<Integer>> {
        X x;
        public SubsetCallable(X x) {
            this.x = x;
        }
        public List<Integer> call() {
            return Util.getSubsetOfX(x);
        }
    }
    

    然后你可以创建一个 ExecutorService 使用中的方法之一 Executors . 使用哪种方法取决于您的可用资源和所需的执行模型—它们都在文档中描述。一旦你创建了 ,只需创建一个 SubsetCallable 对于每个实例 并将其传递给服务来运行它。我想可能是这样的:

    ExecutorService exec = ...;
    List<SubsetCallable> callables = new LinkedList<SubsetCallable>();
    for (X x : lx) {
        callables.append(new SubsetCallable(x));
    }
    List<Future<List<Integer>>> futures = exec.invokeAll(lc);
    for (Future<List<Integer>> f : futures) {
        li.add(f.get());
    }
    

    这样,您可以将密集的计算委托给其他线程,但仍然只能访问一个线程中的结果列表,因此您不必担心同步问题(正如winsharp93所指出的, ArrayList 与大多数Java的标准集合一样,它是不同步的,因此对于并发访问来说并不安全。)

        2
  •  1
  •   Matthias    14 年前

    看到了吗 Class ArrayList

    请注意,此实现不是 已同步。如果有多个线程 访问ArrayList实例 同时,至少有一个 在结构上,它必须是同步的 外部(结构修改 一个或多个元素,或显式 调整背衬阵列的大小;仅仅 结构上的修改。)这是 在某个对象上同步 自然地封装了列表。如果没有 这样的对象存在,列表应该是 使用 Collections.synchronizedList方法。 防止意外不同步 访问列表:

    List list = Collections.synchronizedList(new ArrayList(...));
    

    但要小心:同步会带来巨大的性能代价。这可能会降低使用多个线程所获得的性能(尤其是在计算速度相当快的情况下)。
    因此,尽可能避免访问那些同步的集合。首选线程本地列表,然后可以使用将其与共享列表合并 全部 .