2014-01-24 65 views
0

我想并行化一些代码,它使用“常量”类中的静态字段。在目前的代码基本是这样的用Java为每个线程创建一个实例字段

public class myClass{ 

    public class Constants{ 
      public static int constant; 
    } 


    public static void main(String[] args){ 
      for(int i = 0 ; i<10 ; i++){ 
       Constants.constant = i; 
       System.out.println(Constants.constant/2); 
      } 
    } 
} 

显然循环内的代码更加严重依赖于恒类,它本身要复杂得多。我想要做的是为循环的每次迭代创建一个线程,并分别进行所有计算,同时控制线程数量(现在我正在使用一个简单的信号量)。 现在很明显在上面的代码中,Constants类是在线程之间共享的,因此不能被每个线程更新而不更新所有的线程。

所以我的问题是:是否有无论如何使我的常量类能够有一个实例为每个线程,所有虽然能够以静态方式访问其字段?

回答

0

你所描述的是一个本地:http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html。这是一件好事使用。然而,正如Affe指出的那样,你不能在代码中使用它,因为只有一个类的实例和它的静态成员(每个类加载器)。如果您的Constants类是可以并行构建好几个副本的东西,然后将它们合并在一起,则应通过删除“static”来使Constants.constant成为实例变量。然后创建一个线程局部MyClass中,像这样:

private ThreadLocal<Constants> constants = new ThreadLocal<Constants> { 
    @Override protected Integer initialValue() { 
     return nextId.getAndIncrement(); 
    } 
} 

一旦你的线程完成更新他们的本地对象,就可以把它们粘到共享ArrayBlockingQueue。您的主线程可以将它们全部出列并按照您的愿望合并它们。

另一件需要注意的事情是,如果您的迭代次数可能会变化很多,但您不想要那么多,您可能希望在循环的每次迭代中使用线程池执行程序而不是一个线程线程。 (创建线程代价高昂,许多并发线程占用内存和操作系统调度资源。)

+0

不是。如果他将值存储在静态字段中,则每个类加载器仍然只有一个值。 – Affe

+0

是的,你是对的。我没有注意到这一点。让我编辑答案... – snoopy

+0

展望ThreadLocal;基本上每次迭代都需要很多资源,它完全消耗了它所在的vcpu,所以我真的只需要每个vcpu(大约)一个线程。因此,一次只能运行很少的线程,并且在每次迭代的运行时和内存使用情况下,开销将可以忽略不计。 –

相关问题