【问题标题】:accessing shared variable from inside a Runnable class从 Runnable 类内部访问共享变量
【发布时间】:2011-11-01 03:15:51
【问题描述】:

我需要在我的 Main 类的 main() 方法中定义一个共享变量。我需要两个线程才能访问该共享变量。我通过实现 Runnable 接口并实现接口的抽象 run() 方法来创建线程。如何从实现 Runnable 接口的类中定义的 run() 方法中引用 Main 类的 main() 方法中定义的共享变量?显然,仅按名称调用它们是行不通的 - 因为它们出现在我的 Runnable 类的范围之外。

编辑 - 抱歉,这是一个简单的例子

public Class DoThread implements Runnable {

    public void run(){
        sharedVar += 1
    }


}

在一个单独的 .class 文件中:

public Class Main {

    public static void main(String[] args) {
        int sharedVar = 0;

        Thread t1 = new Thread(new DoThread());
        Thread t2 = new Thread(new DoThread());

        t1.start();
        t2.start();

        t1.join();
        t2.join();

    }


}

所以我应该创建一个对象来存储共享变量,然后在创建线程时将该对象传递给 DoThread() 构造函数吗?我有时会在 java 通过 ref 或通过 var 时感到困惑,所以如果我这样做,t1 对共享 var 的更改会被 t2 看到吗?

【问题讨论】:

  • 总是尝试发布SSCCE

标签: java multithreading shared-memory


【解决方案1】:

好吧,如果您声明一个 local 变量,您将无法在该方法中创建的类之外的任何地方引用它。

您在哪里实施Runnable?如果它在同一个类中,那么您可以将其设为实例变量并将main 设置在您从中创建线程的同一实例上,或者将其设为静态变量。如果Runnable 在不同的类中实现,那么当您构造该类的实例时,您可以为其提供所需的数据 - 目前尚不清楚这究竟意味着什么......正如其他人所说,代码将是有用。 (例如,线程是否需要能够看到原始数据中的变化?)

顺便说一句,线程是相对先进的,而在类之间传播数据是相对基本的。如果您是 Java 新手,我建议您从比线程更简单的事情开始。

编辑:对于您的示例,您应该使用AtomicInteger,如下所示:

import java.util.concurrent.atomic.AtomicInteger;

class DoThread implements Runnable {

    private final AtomicInteger counter;

    DoThread(AtomicInteger counter) {
        this.counter = counter;
    }

    public void run() {
        counter.incrementAndGet();
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {
        AtomicInteger shared = new AtomicInteger(0);

        Thread t1 = new Thread(new DoThread(shared));
        Thread t2 = new Thread(new DoThread(shared));

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println(shared.get()); // Prints 2
    }
}

【讨论】:

  • @Dave:我已经给出了一个如何更改代码的示例。我仍然认为,如果在不同对象之间共享数据对您来说相对较新,那么您可能还没有为线程带来的额外困难做好准备。
【解决方案2】:

这是 PassByRef 更有效的地方。将您的变量引用传递给两个可运行实例。就是这样......从那时起,它就可以在你的 run 方法中被引用了。

例如:

线程 th1 = 新线程 (Myrunnable(varRef))。其他线程也一样

【讨论】:

    【解决方案3】:

    您需要传递对共享值的引用。如果它还不是引用,则需要将其更改为 AtomicReference、AtomicInt 等或要共享的值的数组。

    【讨论】:

      【解决方案4】:

      代码会很有用。

      如果您使用的是匿名类,则可以将变量声明为final,并且可以在匿名类中访问它们。

      public void main(String[] args) {
          final int myvar = 0;
          new Thread(new Runnable() {
              public void run() {
                  System.out.println("myvar: "+myvar);
              }
          }).start();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-15
        • 1970-01-01
        • 2018-03-04
        • 2015-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多