【问题标题】:Output result is different while passing argument to thread methods将参数传递给线程方法时输出结果不同
【发布时间】:2017-04-23 21:46:33
【问题描述】:

所以我试图将参数传递给我的线程,但我的输出不符合预期。以下是我的代码:

class BadThreadParam implements Runnable {
    static int c;

    public BadThreadParam( int a, int b ) {
        c = a + b;
    }

    public void run() {
        System.out.println( c );
    }
}

public class BadThreadParamTest {
    public static void main( String[] args ) {
       BadThreadParam shouldBe3 = new BadThreadParam( 1, 2 );
       BadThreadParam shouldBe5 = new BadThreadParam( 3, 12 );
       shouldBe3.run();  // Expect 3 but is 15.  WTF?
       shouldBe5.run();  // Expect 15.
    }
}

我期待的最终输出是:

3
15

但我得到了:

15
15

那么这是线程干扰的问题吗?谁能解释为什么会这样?

【问题讨论】:

    标签: java multithreading static


    【解决方案1】:

    如果你改变了怎么办

    static int c;
    

    private int c;
    

    由于你没有从你的类中访问变量 c,所以它没有理由应该是静态的。如果将其设为静态,则每次更改时,它都会是最后一个值。

    如果您将其更改为私有,则它是一个“实例”变量,它链接到您使用 new BadThreadParam(); 创建的实例;所以输出是赋予该特定实例的值。

    【讨论】:

      【解决方案2】:

      c 是一个静态变量。这意味着当一个线程更改它时,它会为每个人更改。

      你可能打算让它成为一个实例变量。

      【讨论】:

      • 你能再具体一点吗?比如我怎样才能得到想要的输出?
      • 我真的不知道如何才能更具体。
      【解决方案3】:

      我只是重新排序了你的主要方法中的行,这就是区别

      public static void main(String[] args) {
          BadThreadParam shouldBe3 = new BadThreadParam(1, 2);
          shouldBe3.run();
          BadThreadParam shouldBe5 = new BadThreadParam(3, 12);
          shouldBe5.run(); 
      }
      

      这是输出

      3
      15
      

      看看这个以及@JC97@Joe C发布的答案 希望这能消除您对静态变量的疑虑

      【讨论】:

        【解决方案4】:

        您询问您看到的问题是否是由线程干扰引起的。发布的程序中不可能有线程干扰,因为只有一个线程

        你在 Runnable 上调用 run,它在当前线程中执行它。

        如果您想创建一个新线程来执行每个 Runnable,那么您应该将代码更改为

        new Thread(shouldBe3).start();
        new Thread(shouldBe15).start();
        

        然后您将拥有一个具有多个线程的程序。届时将无法保证一个线程将在另一个线程之前打印其输出。

        要确认这一点,您可以添加该行

        System.out.println(Thread.currentThread().getName());
        

        到每个 run 方法的主体和 main 方法。如果它们都打印相同的名称,那么您没有创建任何线程。

        正如其他答案所说,您让第二个构造函数调用覆盖 c 由第一个构造函数调用设置的内容。 static关键字表示变量属于类,不属于任何一个实例,所有实例都访问同一个变量。 c 应该是一个实例变量(删除 static 关键字),以便每个 Runnable 对象都有自己的副本。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-08-21
          • 1970-01-01
          • 1970-01-01
          • 2021-06-30
          • 1970-01-01
          • 2011-02-18
          • 2016-02-23
          相关资源
          最近更新 更多