【问题标题】:Creating fields with a single instance per thread with Java使用 Java 为每个线程创建具有单个实例的字段
【发布时间】:2014-01-24 17:59:49
【问题描述】:

我正在尝试并行化一些使用“常量”类中的静态字段的代码。目前的代码基本上是这样的

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);
          }
    }
}

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

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

【问题讨论】:

    标签: java multithreading concurrency static


    【解决方案1】:

    您所描述的是一个本地化的主题:http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html。使用它是一件好事。但是,正如 Affe 指出的那样,您不能按原样将其与代码一起使用,因为只有一个类实例及其静态成员(每个类加载器)。如果您的 Constants 类可以并行构建多个副本,然后稍后将它们合并在一起,则应该通过删除“静态”使 Constants.constant 成为实例变量。然后在 myClass 中创建一个线程本地,如下所示:

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

    一旦你的线程完成更新它们的本地对象,它们可以将它们粘贴到一个共享的 ArrayBlockingQueue 中。您的主线程可以将它们全部出列并根据需要合并它们。

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

    【讨论】:

    • 并非如此。如果他将值存储在静态字段中,那么每个类加载器仍然只有一个值。
    • 查看 ThreadLocal;基本上每次迭代都占用了太多资源,它完全耗尽了它所在的 vcpu,所以我真的只需要每个 vcpu 一个线程(大约)。所以一次只会有几个线程运行,并且考虑到每次迭代的运行时和内存使用情况,开销可以忽略不计。
    • 我想 field 可以更改为 ThreadLocal&lt;Integer&gt; 并且可以工作。尽管需要重构一个名为 Constants 的类以便可以编辑值的整个概念让我很头疼 :)
    • 基本上每次迭代都会遍历一个数据集(来自一个 txt 文件),计算与该数据集相关的常量,并使用它们来做需要大量类的事情,其中​​大多数类都使用所述常量。所以我可以将一个常量实例传递给其他类,但这似乎很笨拙。
    • 好吧,如果你有不同的常量集,那么每组肯定有一个 Constants 对象是正确的事情,不是吗?但是我们偏离了并行化的原始点。我认为不清楚的是使用多个线程的好处,即有多少。如果您主要是从文件中读取,那么您将受到磁盘速度的限制,这比 CPU 慢得多。那么一个线程就足够了。如果您想从文件中加载的数据中进行一些繁重的计算,那么您可以使用线程数 = 内核数的线程池。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多