【问题标题】:Passing parameters to Java Thread将参数传递给 Java 线程
【发布时间】:2014-01-05 14:42:57
【问题描述】:

我已经看过了:How can I pass a parameter to a Java Thread?

但我不知道具体如何使用它。所以我制作了简单的示例代码来节省您的宝贵时间:

class ThreadParam implements Runnable { 
static int c;

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

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

}

public class ThreadParamTest {
public static void main(String args[]){
    Runnable r = new ThreadParam(1000,2000);
    new Thread(r).start();  
}   
}

为什么这个结果是 0 ?我认为应该是 3000。也许变量“int c”没有分派给 run() 方法。我该如何解决这个问题?

【问题讨论】:

  • 你在 ThreadParam 方法中本地声明了 c

标签: java multithreading


【解决方案1】:

我认为“static int c”的选择是不正确的,因为这意味着 ThreadParam 的所有实例都将“共享”(而且很糟糕)c 的共同值。也就是说,如果您有 2 个单独的 ThreadParams 同时运行,其中一个可能会为 C 提供“错误”值。考虑...

class BadThreadParam implements Runnable {
    static int c;

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

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

class ImmutableThreadParam implements Runnable {
    private final int c;

    public ImmutableThreadParam( 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, 2 );
        shouldBe3.run();  // Expect 3 but is 5.  WTF?
        shouldBe5.run();  // Expect 5.

        ImmutableThreadParam expect3 = new ImmutableThreadParam( 1, 2 );
        ImmutableThreadParam expect5 = new ImmutableThreadParam( 3, 2 );
        expect3.run();  // Expect 3.
        expect5.run();  // Expect 5.
    }
}

如果您将“c”设置为实例的局部变量,则可以克服“2 个单独的 ThreadParams 影响相同的值”的问题。如果你将“private int c”设为final,你就避免了同步的需要。如果您需要在运行中(或从外部)向下变异“c”,现在您正在进入同步的世界......

class ThreadSafeMutableThreadParam implements Runnable {
    private int c;

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

    public synchronized void setC( int c ) {
        this.c = c;
    }

    public synchronized int getC() {
        return c;
    }

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

除此之外,tuxdna 在描述您如何“将参数传递给 Runnable”方面是正确的。 Runnable 无关紧要;您正在将参数传递给一个类(但是您实现了这一点)。如果您需要它们在 run() 中可用,则需要注意同步。

【讨论】:

    【解决方案2】:

    Runnable 只是一个接口,需要你定义一个run() 方法,不多也不少。因此,基本上,您可以随意声明您的类构造函数(您传递两个整数 ab),以便能够从 run() 方法访问它们。

    您还在构造函数中定义了一个局部变量,该变量在构造函数完成后被销毁。这使您的 static int c 值仍为 0

    这里是固定版本:

    class ThreadParam implements Runnable {
        private int c;
    
        public ThreadParam(int a, int b) {
            c = a + b;
        }
    
        public void run() {
            System.out.println(c);
        }
    
    }
    
    public class ThreadParamTest {
    
        public static void main(String args[]) {
            Runnable r = new ThreadParam(1000, 20000);
            new Thread(r).start();
        }
    }
    

    输出是21000(而不是3000

    【讨论】:

    • 这段代码在技术上是正确的,但是“static int c”在这里可能不是最好的选择,因为它意味着所有拥有 ThreadParam 的线程都将共享这个共同的值。此外,每次新的 ThreadParam 更新时,他们都会看到它发生变化。我希望这个声明至少是“private final int c”,以使其成为本地实例且不可变,因此是线程安全的。如果需要在外面发布“c”;创建一个“public int getC() { return c; } 你很高兴。如果打算在运行中或从外部更改“c”,现在你需要通过同步来保护它。
    • @BobKuhar 同意。它(c)应该是私有的。但此代码仅供原作者参考。修好了。
    【解决方案3】:

    c 不应该是静态的,应该在你的构造函数中赋值。 在您的示例中,您已分配给变量 c,而不是字段。

    以下是更正后的代码:

    class ThreadParam implements Runnable { 
    private int c;
    
    public ThreadParam(int a, int b){
        this.c = a+b;
    }
    
    public void run(){
        System.out.println(c);
    }
    
    }
    

    【讨论】:

      【解决方案4】:

      您的“c”变量定义了两次:一次在类级别(使用静态修饰符),一次在 ThreadParam 构造函数中。删除类字段上的“静态”并删除构造函数中的“int”。

      【讨论】:

        【解决方案5】:

        结果为 0,因为在构造函数中您实际上并未将新值分配给 static int c,而是将其分配给局部变量 c

        在构造函数中将int c 更改为c

        【讨论】:

        • +1 另外,发帖者希望c字段是静态的。这意味着ThreadParam 的所有实例共享相同的字段。
        • 我能再问你一个问题吗?在我的示例代码中,在 run() 方法中,如何打印变量“a”?我想证明这一点。
        • 您需要将a 作为另一个字段(非静态)存储在您的ThreadParam 类@user3100921 中。然后就可以打印了。
        猜你喜欢
        • 2010-10-26
        • 2011-02-18
        • 2015-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多