首页 文章

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

提问于
浏览
250

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

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

17 回答

  • 100

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

    public class MyRunnable implements Runnable {
    
       public MyRunnable(Object parameter) {
           // store parameter for later user
       }
    
       public void run() {
       }
    }
    

    并调用它:

    Runnable r = new MyRunnable(param_value);
    new Thread(r).start();
    
  • 4

    从Java 8开始,您可以使用lambda来捕获effectively 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();
    
  • 16

    对于匿名类:

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

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

    命名类:

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

    Thread t = new MyThread(args...);
    t.start();
    

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

    这个答案与这个类似的问题基本相同:How to pass parameters to a Thread object

  • 1

    要创建一个线程,通常可以创建自己的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);
       }
    }
    
  • 3

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

  • 3

    另一个选择;这种方法允许您像使用异步函数调用一样使用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 );
          }
    
      }
    

    }

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

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

  • 323

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

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

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

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

    myRunnable.setMyParam("Goodbye World");
    

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

  • 15

    通过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();
    }
    
  • 1

    通过start()和run()方法传递的参数:

    // Tester
    public static void main(String... args) throws Exception {
        ThreadType2 t = new ThreadType2(new RunnableType2(){
            public void run(Object object) {
                System.out.println("Parameter="+object);
            }});
        t.start("the parameter");
    }
    
    // New class 1 of 2
    public class ThreadType2 {
        final private Thread thread;
        private Object objectIn = null;
        ThreadType2(final RunnableType2 runnableType2) {
            thread = new Thread(new Runnable() {
                public void run() {
                    runnableType2.run(objectIn);
                }});
        }
        public void start(final Object object) {
            this.objectIn = object;
            thread.start();
        }
        // If you want to do things like setDaemon(true); 
        public Thread getThread() {
            return thread;
        }
    }
    
    // New class 2 of 2
    public interface RunnableType2 {
        public void run(Object object);
    }
    
  • 8

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

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

  • 1

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

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

    有一种将参数传递给runnables的简单方法 . 码:

    public void Function(final type variable) {
        Runnable runnable = new Runnable() {
            public void run() {
                //Code adding here...
            }
        };
        new Thread(runnable).start();
    }
    
  • 0

    这个答案来得很晚,但也许有人会发现它很有用 . 它是关于如何将参数传递给 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;
        {
            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();
    

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

  • 2

    您可以从Runnable派生一个类,并在构造期间(比如)传递参数 .

    然后使用Thread.start(Runnable r)启动它;

    如果你的意思是在线程运行时,那么只需在调用线程中保存对派生对象的引用,并调用适当的setter方法(在适当的地方同步)

  • 2

    特别适用于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();
    }
    
  • 7

    在Java 8中,您可以将 lambda 表达式与Concurrency APIExecutorService 一起用作工作的更高级别替代直接使用线程:

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

    private static final ExecutorService executor = Executors.newCachedThreadPool();
    
        executor.submit(() -> {
            myFunction(myParam1, myParam2);
        });
    

    另见 executors javadocs .

  • 36

    在类中创建 extends Threadimplements Runnable 的局部变量 .

    public class Extractor extends Thread {
        public String webpage = "";
        public Extractor(String w){
            webpage = w;
        }
        public void setWebpage(String l){
            webpage = l;
        }
    
        @Override
        public void run() {// l is link
            System.out.println(webpage);
        }
        public String toString(){
            return "Page: "+webpage;
        }}
    

    这样,您可以在运行变量时传递变量 .

    Extractor e = new Extractor("www.google.com");
    e.start();
    

    输出:

    "www.google.com"
    

相关问题