Java 在列表中穿行
我有一个应用程序有点慢。我认为使用线程会更快Java 在列表中穿行,java,multithreading,Java,Multithreading,我有一个应用程序有点慢。我认为使用线程会更快 >,这是我的计划:我的程序有一个 > X类型的对象列表>强> >每个对象X有一个非常大的整数列表< /强>(为了简单起见,我们考虑整数)。 我有一个静态方法(称为getSubsetOfX),它从X的列表中接收对象X,并返回对象X的整数列表。返回的列表是X中包含的所有整数的子集 对于列表中包含的每个X调用此方法。然后我将返回的列表插入整数列表列表中 这是我在精简版中解释的代码: // Class of object X public class X{
>,这是我的计划:我的程序有一个<强> > X类型的对象列表>强> >每个对象X有一个非常大的整数列表< /强>(为了简单起见,我们考虑整数)。 我有一个静态方法(称为getSubsetOfX),它从X的列表中接收对象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));
}
}
}
//对象X的类
公共X类{
公共列表列表x;
...
}
//实用类
公共类Util{
//返回X中包含的整数的子集
公共静态列表getSubsetOfX(X X){…}
}
公共类执行官{
公共静态void main(字符串参数[]){
//让我们假设lx已经充满了数据!
List lx=new ArrayList();
//整数的子集列表
List li=new ArrayList();
对于(X:lx){
//我想将此步骤“线程化”
li.添加(getSubsetOfX(x));
}
}
}
我不知道列表是否允许并发插入。我也不知道如何在其中应用线程。我读了一些关于线程的文章,但是,由于run()方法不返回任何内容,如何将该方法getSubsetOfX(X X)并行化
你能帮我做这个吗
我不知道列表是否允许并发插入
见:
请注意,此实现不可用
同步的。如果有多个线程
访问ArrayList实例
同时,以及至少一个
线程修改列表
从结构上讲,它必须是同步的
外部。(A)结构修改
是添加或删除的任何操作
一个或多个元素,或显式地
调整支持数组的大小;仅
不允许设置元素的值
结构修改。)这是
通常由
在某个对象上同步
自然地封装了列表。如果没有
如果存在这样的对象,则列表应为
使用
Collections.synchronizedList方法。
这最好在创建时完成,以便
防止意外不同步
访问列表:
List list = Collections.synchronizedList(new ArrayList(...));
但要小心:同步带来了巨大的性能成本。这可能会影响使用多个线程所获得的性能(特别是当计算速度相当快时)因此,尽可能避免访问那些同步的集合。首选线程本地列表,然后使用AddAll将其与共享列表合并 我不知道列表是否允许并发插入 见: 请注意,此实现不可用 同步的。如果有多个线程 访问ArrayList实例 同时,以及至少一个 线程修改列表 从结构上讲,它必须是同步的 外部。(A)结构修改 是添加或删除的任何操作 一个或多个元素,或显式地 调整支持数组的大小;仅 不允许设置元素的值 结构修改。)这是 通常由 在某个对象上同步 自然地封装了列表。如果没有 如果存在这样的对象,则列表应为 使用 Collections.synchronizedList方法。 这最好在创建时完成,以便 防止意外不同步 访问列表:
List list = Collections.synchronizedList(new ArrayList(...));
但要小心:同步带来了巨大的性能成本。这可能会影响使用多个线程所获得的性能(特别是当计算速度相当快时)因此,尽可能避免访问那些同步的集合。首选线程本地列表,然后使用AddAll将其与共享列表合并 需要澄清的是,
getSubsetOfX()
是一个需要很长时间的调用,对吗
对于这类任务,我建议您看看Java的Executor
s。第一步是创建一个在给定的x
实例上运行getSubsetOfX(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 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的标准集合一样,是不同步的,因此并发访问不安全。)需要澄清的是,getSubsetOfX()
是一个需要很长时间的调用,对吗
对于这类任务,我建议您看看Java的Executor
s。第一步是创建一个在给定的x
实例上运行getSubsetOfX(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 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标准集合一样,是不同步的,因此并发访问不安全。)Hi@winsharp93。你有什么建议可以帮助我在程序中并行执行这一步骤吗?RegardsWell-这取决于您的getSubsetOfX。然而,在许多情况下,使用David Zaslavsky的例子应该是不错的。你有什么建议可以帮助我在程序中并行执行这一步骤吗?RegardsWell-这取决于您的getSubsetOfX。然而,在许多情况下,使用David Zaslavsky的例子应该是不错的。是的@David,慢速方法是getSubsetOfX(X)。这个exec.invokeAll()是并行运行Callables还是linnear运行Callables?ThanksIt取决于您使用哪个ExecutorService
实现。