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

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


当前回答

不,你不能将参数传递给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”的对象的数据完整性。数据现在将存在于两个不同的线程中,因此您必须确保它是线程安全的。

其他回答

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

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

Android专用

为了回调的目的,我通常使用输入参数实现自己的泛型Runnable:

public interface Runnable<TResult> {
    void run(TResult result);
}

用法很简单:

myManager.doCallbackOperation(new Runnable<MyResult>() {
    @Override
    public void run(MyResult result) {
        // do something with the result
    }
});

在经理:

public void doCallbackOperation(Runnable<MyResult> runnable) {
    new AsyncTask<Void, Void, MyResult>() {
        @Override
        protected MyResult doInBackground(Void... params) {
            // do background operation
            return new MyResult(); // return resulting object
        }

        @Override
        protected void onPostExecute(MyResult result) {
            // execute runnable passing the result when operation has finished
            runnable.run(result);
        }
    }.execute();
}

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

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

这个答案来得很晚,但也许有人会觉得它有用。它是关于如何在不声明命名类的情况下将参数传递给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();

当然,您可以将start的执行推迟到某个更方便或合适的时刻。这取决于你init方法的签名(所以它可能需要更多和/或不同的参数),当然甚至它的名字,但基本上你得到了一个想法。

事实上,还有另一种将参数传递给匿名类的方法,即使用初始化块。考虑一下:

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

    new Thread(new Runnable() {
        private String myParam;
        private int myOtherParam;
        // instance initializer
        {
            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();

所有都发生在初始化程序块内部。