有人能告诉我如何将参数传递给线程吗?

另外,匿名类是如何工作的?


当前回答

首先,我想指出其他答案都是正确的。 但是,在构造函数中使用形参可能对所有人来说都不是最好的主意。

在很多情况下,你会想要使用“匿名内部类”,并重写run()方法,因为为每个用途定义特定的类是很痛苦的。 (新MyRunnable(){…})

在创建Runnable时,参数可能无法在构造函数中传递。例如,如果你将这个对象传递给一个方法,这个方法将在单独的线程中执行一些工作,然后调用你的runnable,将该工作的结果应用到它。

在这种情况下,使用如下方法: public MyRunnable withParameter(对象参数),可能是更有用的选择。

我并不是说这是解决问题的最好办法,但它可以解决问题。

其他回答

要创建线程,通常需要创建自己的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);
   }
}

创建线程时,需要一个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();

如果你想在线程运行时改变参数,你可以简单地给你的runnable类添加一个setter方法:

public void setMyParam(String value){
    this.myParam = value;
}

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

myRunnable.setMyParam("Goodbye World");

当然,如果您希望在参数更改时触发一个操作,则必须使用锁,这使事情变得相当复杂。

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

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

还有一个选择;这种方法允许您像使用异步函数调用一样使用Runnable项。如果你的任务不需要返回一个结果,例如,它只是执行一些操作,你不需要担心如何传递回一个“结果”。

此模式允许您重用需要某种内部状态的项。当不在构造函数中传递参数时,需要注意调节程序对参数的访问。如果您的用例涉及不同的调用者,您可能需要更多的检查。

public class MyRunnable implements Runnable 
{
  private final Boolean PARAMETER_LOCK  = false;
  private X parameter;

  public MyRunnable(X parameter) {
     this.parameter = parameter;
  }

  public void setParameter( final X newParameter ){

      boolean done = false;
      synchronize( PARAMETER_LOCK )
      {
          if( null == parameter )
          {
              parameter = newParameter;
              done = true;
          }
      }
      if( ! done )
      {
          throw new RuntimeException("MyRunnable - Parameter not cleared." );
      }
  }


  public void clearParameter(){

      synchronize( PARAMETER_LOCK )
      {
          parameter = null;
      }
  }


  public void run() {

      X localParameter;

      synchronize( PARAMETER_LOCK )
      {
          localParameter = parameter;
      }

      if( null != localParameter )
      {
         clearParameter();   //-- could clear now, or later, or not at all ...
         doSomeStuff( localParameter );
      }

  }

}

线程=新的线程(新的MyRunnable(参数)); t.start ();

如果您需要处理的结果,您还需要在子任务完成时协调MyRunnable的完成。你可以传递一个回调或者只是等待线程't',等等。

不,你不能将参数传递给run()方法。签名告诉您(它没有参数)。可能最简单的方法是使用一个专门构建的对象,该对象接受构造函数中的形参并将其存储在final变量中:

public class WorkingTask implements Runnable
{
    private final Object toWorkWith;

    public WorkingTask(Object workOnMe)
    {
        toWorkWith = workOnMe;
    }

    public void run()
    {
        //do work
    }
}

//...
Thread t = new Thread(new WorkingTask(theData));
t.start();

一旦你这样做了-你必须小心你传递到“WorkingTask”的对象的数据完整性。数据现在将存在于两个不同的线程中,因此您必须确保它是线程安全的。