【问题标题】:Counting a single variable in multiple threads在多个线程中计算单个变量
【发布时间】:2011-04-06 12:27:21
【问题描述】:

我有以下可运行的类。

public class OnesRun implements Runnable {

    public int ones = 0;

    private int passendNumber;

    public OnesRun(int passendNumber) {
        this.passendNumber = passendNumber;
    }

    public void run() {
        if (passendNumber == 1)
            ones++;
    }

}

如果遇到此类的每个实例,都应增加ones 的值。

执行完所有线程后,我想从类外读取ones 的值。

  1. 如何增加ones 线程安全?
  2. 如何访问 ones 来自这个班级之外? 通过静态变量?或者我可以把它放到应用程序中吗 上下文?

编辑:

我希望下面的伪代码能让我的意图更清楚。

OnesRun.ones = getCurrentValueOnes();

while ( (number = readNumbersFromFile) != null) {
   threadPool.execute(new OnesRun(number));
}

print("Overall values of ones " + OnesRun.ones);

【问题讨论】:

  • 请注意,伪代码很可能会执行您想要的操作,因为打印的值将介于 0 和实际数量之间。原因是您无法确定在访问计数之前执行了所有 OnesRun 实例。
  • 没错。我必须等到所有线程都执行完毕。

标签: java multithreading thread-safety runnable


【解决方案1】:

如何增加线程安全的?

您可以使用AtomicInteger

我如何从这个类之外访问那些?通过静态变量?或者我可以把它放到应用程序上下文中吗?

你可以使用一个简单的getter。还是我错过了什么?

更新

根据您的更新,我将如何修改您的代码示例:

public class OnesRun implements Runnable {

    private static final AtomicInteger ones = new AtomicInteger();

    private final int passendNumber;

    public OnesRun(int passendNumber) {
        this.passendNumber = passendNumber;
    }

    public void run() {
        if (passendNumber == 1)
            OnesRun.ones.incrementAndGet();
    }

    public static void setOnes(int newValue) {
        ones.set(newValue);
    }

    public static int getOnes() {
        return ones.get()
    }
}

...

OnesRun.setOnes(getCurrentValueOnes());

while ( (number = readNumbersFromFile) != null) {
   threadPool.execute(new OnesRun(number));
}

print("Overall values of ones " + OnesRun.getOnes());

除了已经讨论过的内容(将 ones 设为 private static AtomicInteger 并添加 getter/setter 对)之外,我将两个成员都设为了 final,如果可能,这始终是可取的,尤其是在并发代码中。

另请注意,AtomicInteger 保留为实现细节 - 它不会被类的公共接口公开。

【讨论】:

  • 另外,将 ones 设置为 private 而不是 public 以强制使用 getter。
  • 但是在所有线程都完成后,我必须创建这个类的一个新实例并调用 getter,不是吗?
  • @Bernhard V,如果您想在每个OnesRun 实例之间共享​​> ones,请将其设为static,并使用static getter。
  • 我已经编辑了我的问题。我希望这能帮助你理解我。
【解决方案2】:

使用 AtomicInteger(线程安全)和静态属性。

public class OnesRun implements Runnable {
    private static final AtomicInteger ones = new AtomicInteger();

    private int passendNumber;

    public OnesRun(int passendNumber) {
        this.passendNumber = passendNumber;
    }

    public void run() {
        if (passendNumber == 1) {
            ones.incrementAndGet();
        }
    }

    public static AtomicInteger getOnes() {
        return ones;
    }
}


OnesRun.getOnes().set(getCurrentValueOnes());

while ( (number = readNumbersFromFile) != null) {
    threadPool.execute(new OnesRun(number));
}

print("Overall values of ones " + OnesRun.getOnes().get());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多