向Java线程传递参数

向Java线程传递参数,java,multithreading,Java,Multithreading,我已经看到: 但我不知道该怎么用。因此,我制作了简单的samle代码,以节省您宝贵的时间: 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 stat

我已经看到:

但我不知道该怎么用。因此,我制作了简单的samle代码,以节省您宝贵的时间:

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不是dispatch to run方法。如何解决此问题?

结果为0,因为在构造函数中,您实际上并没有将新值赋给静态int c,而是将其赋给局部变量c


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

结果为0,因为在构造函数中,您实际上并没有将新值赋给静态int c,而是将其赋给局部变量c


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

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

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

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

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

}

Runnable只是一个接口,它要求您定义一个run方法。所以,本质上,您可以自由地以任何方式声明类构造函数,只要您传递两个整数a和b,就可以从run方法访问它们

此外,您正在构造函数中定义一个局部变量,该局部变量在构造函数完成后被销毁。这使得静态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,Runnable只是一个需要定义run方法的接口,不多也不少。所以,本质上,您可以自由地以任何方式声明类构造函数,只要您传递两个整数a和b,就可以从run方法访问它们

此外,您正在构造函数中定义一个局部变量,该局部变量在构造函数完成后被销毁。这使得静态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的所有实例都将共享c的一个公共值。也就是说,如果你同时有2个线程线程,它们中的一个可能会出现错误的值。
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设置为实例的本地,则可以克服两个单独的ThreadParams影响相同值的问题。如果将私有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时是正确的。可运行的是无关紧要的;您正在将参数传递给一个类,但是您实现了这一点。如果您需要它们在运行中可用,则需要注意同步。

我认为选择static int c是不正确的,因为这意味着ThreadParam的所有实例都将共享c的公共值。也就是说,如果你同时有2个线程线程,它们中的一个可能会出现错误的值。
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设置为实例的本地,则可以克服两个单独的ThreadParams影响相同值的问题。如果将私有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时是正确的。可运行的是无关紧要的;您正在将参数传递给一个类,但是您实现了这一点。如果您需要它们在运行中可用,则需要注意同步。

您在方法ThreadParam中本地声明了c您在方法ThreadParam+1中本地声明了c,海报可能不希望c字段是静态的。这意味着ThreadParam的所有实例共享同一字段。我可以再问你一个问题吗?在我的示例代码中,在run方法中,如何打印变量a?我想展示一下。您需要在ThreadParam类@user3100921中将a存储为另一个非静态字段。然后你可以打印它。+1同样,海报不希望c字段是静态的。这意味着ThreadParam的所有实例共享同一字段。我可以再问你一个问题吗?在我的示例代码中,在run方法中,如何打印变量a?我想展示给大家看
您需要在ThreadParam类@user3100921中将a存储为另一个非静态字段。这段代码在技术上是正确的,但是静态int c可能不是最好的选择,因为它意味着所有具有ThreadParam的线程都将共享这个公共值。此外,每次新的ThreadParam更新时,他们都会看到它的变化。我希望这个声明至少是私有的final int c,以使它成为本地的、不可变的实例,从而实现线程安全。如果需要在外部发布c;创建一个公共int getC{return c;}就可以了。如果打算在运行中或从外部更改c,现在需要通过同步来保护它。@BobKuhar同意。它应该是私人的。但本规范仅供原作者参考。修复了它。这段代码在技术上是正确的,但是静态int c可能不是这里的最佳选择,因为它意味着所有具有ThreadParam的线程都将共享这个公共值。此外,每次新的ThreadParam更新时,他们都会看到它的变化。我希望这个声明至少是私有的final int c,以使它成为本地的、不可变的实例,从而实现线程安全。如果需要在外部发布c;创建一个公共int getC{return c;}就可以了。如果打算在运行中或从外部更改c,现在需要通过同步来保护它。@BobKuhar同意。它应该是私人的。但本规范仅供原作者参考。修好了。