如何将参数传递给Java线程?

Ste*_*eve 280 java multithreading

谁能告诉我如何将参数传递给线程?

此外,它如何为匿名类工作?

Aln*_*tak 355

您需要将构造函数中的参数传递给Runnable对象:

public class MyRunnable implements Runnable {

   public MyRunnable(Object parameter) {
       // store parameter for later user
   }

   public void run() {
   }
}
Run Code Online (Sandbox Code Playgroud)

并调用它:

Runnable r = new MyRunnable(param_value);
new Thread(r).start();
Run Code Online (Sandbox Code Playgroud)

  • @jasonm不,它是一个构造函数 - 构造函数没有返回类型. (7认同)
  • @IsaacKleinman 好吧,无论如何你都必须这样做,除非你扩展线程。在这种情况下,这个解决方案仍然有效——只需将“implements Runnable”更改为“extends Thread”,将“Runnable”更改为“Thread”,将“new Thread(r)”更改为“r”。 (2认同)

Nic*_*cue 108

对于匿名类:

回答问题编辑,这里是匿名类的工作原理

   final X parameter = ...; // the final is important
   Thread t = new Thread(new Runnable() {
       p = parameter;
       public void run() { 
         ...
       };
   t.start();
Run Code Online (Sandbox Code Playgroud)

命名类:

你有一个扩展Thread(或实现Runnable)的类和一个带有你想要传递的参数的构造函数.然后,当您创建新线程时,您必须传入参数,然后启动线程,如下所示:

Thread t = new MyThread(args...);
t.start();
Run Code Online (Sandbox Code Playgroud)

Runnable是比Thread BTW更好的解决方案.所以我更喜欢:

   public class MyRunnable implements Runnable {
      private X parameter;
      public MyRunnable(X parameter) {
         this.parameter = parameter;
      }

      public void run() {
      }
   }
   Thread t = new Thread(new MyRunnable(parameter));
   t.start();
Run Code Online (Sandbox Code Playgroud)

这个答案与这个类似的问题基本相同:如何将参数传递给Thread对象

  • 我有类似于你的匿名类示例的代码,除了我直接从`run()`方法访问`parameter`而不使用像`p`这样的字段.它似乎工作.通过不事先将`parameter`复制到`p`,是否有一些微妙的多线程的东西? (2认同)

dfa*_*dfa 41

通过Runnable或Thread类的构造函数

class MyThread extends Thread {

    private String to;

    public MyThread(String to) {
        this.to = to;
    }

    @Override
    public void run() {
        System.out.println("hello " + to);
    }
}

public static void main(String[] args) {
    new MyThread("world!").start();
}
Run Code Online (Sandbox Code Playgroud)

  • +1表示如何扩展Thread而不是实现Runnable. (5认同)

Cro*_*max 20

这个答案来得很晚,但也许有人会发现它很有用.它是关于如何将参数传递给a Runnable甚至没有声明命名类(对于内联器很方便):

String someValue = "Just a demo, really...";
new Thread(new Runnable() {
    private String myParam;
    public Runnable init(String myParam) {
        this.myParam = myParam;
        return this;
    }
    @Override
    public void run() {
        System.out.println("This is called from another thread.");
        System.out.println(this.myParam);
    }
}.init(someValue)).start();
Run Code Online (Sandbox Code Playgroud)

当然,您可以将执行推迟start到一些更方便或适当的时刻.这取决于你的init方法签名(所以它可能需要更多和/或不同的论点),当然甚至是它的名字,但基本上你会有一个想法.

事实上,还有另一种方法可以使用初始化程序块将参数传递给匿名类.考虑一下:

String someValue = "Another demo, no serious thing...";
int anotherValue = 42;

new Thread(new Runnable() {
    private String myParam;
    private int myOtherParam;
    {
        this.myParam = someValue;
        this.myOtherParam = anotherValue;
    }
    @Override
    public void run() {
        System.out.println("This comes from another thread.");
        System.out.println(this.myParam + ", " + this.myOtherParam);
    }
}).start();
Run Code Online (Sandbox Code Playgroud)

所有这些都发生在初始化程序块内部.


jwo*_*ard 17

创建线程时,需要一个实例Runnable.传递参数的最简单方法是将其作为参数传递给构造函数:

public class MyRunnable implements Runnable {

    private volatile String myParam;

    public MyRunnable(String myParam){
        this.myParam = myParam;
        ...
    }

    public void run(){
        // do something with myParam here
        ...
    }

}

MyRunnable myRunnable = new myRunnable("Hello World");
new Thread(myRunnable).start();
Run Code Online (Sandbox Code Playgroud)

如果您希望在线程运行时更改参数,则只需将setter方法添加到runnable类:

public void setMyParam(String value){
    this.myParam = value;
}
Run Code Online (Sandbox Code Playgroud)

一旦你有了这个,你可以通过这样调用来改变参数的值:

myRunnable.setMyParam("Goodbye World");
Run Code Online (Sandbox Code Playgroud)

当然,如果要在参数更改时触发操作,则必须使用锁定,这会使事情变得更加复杂.


mey*_*eyi 10

我知道我迟到了几年,但我遇到了这个问题并采取了非正统的方法。我想在不创建新课程的情况下做到这一点,所以这就是我想出的:

int x = 0;
new Thread((new Runnable() {
     int x;
     public void run() {
        // stuff with x and whatever else you want
     }
     public Runnable pass(int x) {
           this.x = x;
           return this;
     }
}).pass(x)).start();
Run Code Online (Sandbox Code Playgroud)


Mne*_*nth 9

要创建一个线程,通常可以创建自己的Runnable实现.将参数传递给此类的构造函数中的线程.

class MyThread implements Runnable{
   private int a;
   private String b;
   private double c;

   public MyThread(int a, String b, double c){
      this.a = a;
      this.b = b;
      this.c = c;
   }

   public void run(){
      doSomething(a, b, c);
   }
}
Run Code Online (Sandbox Code Playgroud)


bru*_*nde 8

您可以根据需要扩展或提供参数.文档中有一些简单的例子.我会把它们移到这里:Thread classRunnable class

 class PrimeThread extends Thread {
     long minPrime;
     PrimeThread(long minPrime) {
         this.minPrime = minPrime;
     }

     public void run() {
         // compute primes larger than minPrime
          . . .
     }
 }

 PrimeThread p = new PrimeThread(143);
 p.start();

 class PrimeRun implements Runnable {
     long minPrime;
     PrimeRun(long minPrime) {
         this.minPrime = minPrime;
     }

     public void run() {
         // compute primes larger than minPrime
          . . .
     }
 }


 PrimeRun p = new PrimeRun(143);
 new Thread(p).start();
Run Code Online (Sandbox Code Playgroud)


Pau*_*ams 7

编写一个实现Runnable的类,并在适当定义的构造函数中传递您需要的任何内容,或编写一个使用适当定义的构造函数扩展Thread的类,该构造函数使用适当的参数调用super().


Stu*_*all 6

在 Java 8 中,您可以将lambda表达式与并发 API一起使用,ExecutorService作为直接使用线程的更高级别的替代品:

newCachedThreadPool()创建一个线程池,根据需要创建新线程,但在可用时将重用先前构造的线程。这些池通常会提高执行许多短期异步任务的程序的性能。

    private static final ExecutorService executor = Executors.newCachedThreadPool();

    executor.submit(() -> {
        myFunction(myParam1, myParam2);
    });
Run Code Online (Sandbox Code Playgroud)

另请参阅executors javadocs


Jef*_*f G 5

从Java 8开始,您可以使用lambda来捕获有效最终的参数.例如:

final String param1 = "First param";
final int param2 = 2;
new Thread(() -> {
    // Do whatever you want here: param1 and param2 are in-scope!
    System.out.println(param1);
    System.out.println(param2);
}).start();
Run Code Online (Sandbox Code Playgroud)