Jak mogę przekazać parametr do wątku Java?

Czy ktoś może mi zasugerować Jak mogę przekazać parametr do wątku?

Również, jak to działa dla anonimowych klas?

Author: slhck, 2009-05-18

17 answers

Musisz przekazać parametr w konstruktorze do obiektu Runnable:

public class MyRunnable implements Runnable {

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

   public void run() {
   }
}

I wywołaj go w ten sposób:

Runnable r = new MyRunnable(param_value);
new Thread(r).start();
 314
Author: Alnitak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-15 16:05:16

Dla klas anonimowych:

W odpowiedzi na pytania edycje oto jak to działa dla anonimowych klas

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

Nazwane klasy:

Masz klasę, która rozszerza wątek (lub implementuje Runnable) i konstruktor z parametrami, które chcesz przekazać. Następnie, gdy tworzysz nowy wątek, musisz podać argumenty, a następnie rozpocząć wątek, coś w tym stylu:

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

Runnable jest o wiele lepszym rozwiązaniem niż Thread BTW. Więc ... preferuję:

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

Ta odpowiedź jest zasadniczo taka sama jak to podobne pytanie: Jak przekazać parametry do obiektu wątku

 98
Author: Nick Fortescue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:33

Poprzez konstruktor klasy Runnable lub 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();
}
 36
Author: dfa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 10:47:25

Kiedy tworzysz wątek, potrzebujesz instancji Runnable. Najprostszym sposobem przekazania parametru jest przekazanie go jako argumentu konstruktorowi:

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

Jeśli chcesz zmienić parametr podczas działania wątku, możesz po prostu dodać metodę setter do swojej klasy runnable:

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

Gdy już to masz, możesz zmienić wartość parametru, wywołując w ten sposób:

myRunnable.setMyParam("Goodbye World");

Oczywiście, jeśli chcesz wywołać akcję, gdy parametr jest zmieniony, trzeba będzie użyć zamków, co sprawia, że rzeczy znacznie bardziej skomplikowane.

 16
Author: jwoolard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 10:51:16

Ta odpowiedź przychodzi bardzo późno, ale może komuś się przyda. Chodzi o to, jak przekazać parametr(y) do Runnable bez deklarowania nazwanej klasy (przydatne dla inlinerów):

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

Oczywiście możesz odłożyć wykonanie start na jakiś wygodniejszy lub odpowiedni moment. I to od Ciebie zależy, jaka będzie sygnatura metody init (więc może to wymagać więcej i / lub różnych argumentów) i oczywiście nawet jej nazwa, ale w zasadzie masz pomysł.

W rzeczywistości istnieje również inny sposób przekazywania parametru do anonimowej klasy, przy użyciu bloków inicjalizatora. Rozważ to:

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

Więc wszystko dzieje się wewnątrz bloku inicjalizatora.

 13
Author: Cromax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-24 13:04:02

Aby utworzyć wątek, Zwykle tworzysz własną implementację Runnable. Przekazuje parametry do wątku w konstruktorze tej klasy.

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);
   }
}
 9
Author: Mnementh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-21 07:15:30

Możesz albo rozszerzyć Thread class lub Runnable class i podaj parametry, jak chcesz. Istnieją proste przykłady w docs . Umieszczę je tutaj:

 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();
 8
Author: bruno conde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 10:46:38

Albo napisz klasę, która implementuje Runnable i przekaż wszystko, czego potrzebujesz w odpowiednio zdefiniowanym konstruktorze, albo napisz klasę, która rozszerza wątek o odpowiednio zdefiniowany konstruktor, który wywołuje super () z odpowiednimi parametrami.

 7
Author: PaulJWilliams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 10:41:02

Począwszy od Javy 8, można używać lambda do przechwytywania parametrów, które są efektywnie ostateczne . Na przykład:

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();
 4
Author: Jeff G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:08

Możesz wyprowadzić klasę z Runnable i podczas budowy (powiedzmy) przekazać parametr.

Następnie uruchom go za pomocą wątku.start(Runnable r);

Jeśli masz na myśli podczas gdy wątek jest uruchomiony, po prostu przytrzymaj odniesienie do swojego pochodnego obiektu w wątku wywołującym i wywołaj odpowiednie metody settera (synchronizujące w stosownych przypadkach)

 3
Author: Brian Agnew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-18 10:41:41

Parametr przechodzący przez metody start() I 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);
}
 3
Author: Java42,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-11 21:01:52

Istnieje prosty sposób przekazywania parametrów do runnables. Kod:

public void Function(final type variable) {
    Runnable runnable = new Runnable() {
        public void run() {
            //Code adding here...
        }
    };
    new Thread(runnable).start();
}
 2
Author: Chromium,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 03:18:22

W Javie 8 można używać wyrażeń lambda z API współbieżności i ExecutorService jako zamiennika wyższego poziomu do pracy bezpośrednio z wątkami:

newCachedThreadPool() tworzy pulę wątków, która tworzy nowe wątki w razie potrzeby, ale wykorzysta wcześniej skonstruowane wątki, gdy są dostępny. Pule te zazwyczaj poprawiają wydajność programów, które wykonują wiele krótkotrwałych zadań asynchronicznych.

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

    executor.submit(() -> {
        myFunction(myParam1, myParam2);
    });

Zobacz executors javadocs .

 2
Author: Stuart Cardall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-29 09:53:51

Jeszcze jedna opcja; takie podejście pozwala na użycie elementu Runnable jak asynchroniczne wywołanie funkcji. Jeśli Twoje zadanie nie musi zwracać wyniku, np. po prostu wykonuje jakąś akcję, nie musisz się martwić o to, jak przekazujesz z powrotem "wynik".

Ten wzorzec pozwala na ponowne użycie elementu, gdzie potrzebny jest jakiś wewnętrzny stan. Gdy nie przekazujemy parametrów w konstruktorze, potrzebna jest opieka nad mediacją dostępu programów do parametrów. Możesz potrzebować więcej kontroli, jeśli twój przypadek użycia dotyczy różnych rozmówców, itp.

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

  }

}

Thread t = new Thread (new MyRunnable (parametr)); t. start ();

Jeśli potrzebujesz wyniku przetwarzania, musisz również koordynować zakończenie MyRunnable po zakończeniu zadania podrzędnego. Można przekazać połączenie z powrotem lub po prostu czekać na wątku "t", itp.

 1
Author: will,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-22 22:19:56

Specjalnie dla Androida

W celach wywołania zwrotnego zazwyczaj implementuję swój własny ogólny Runnable z parametrami wejściowymi:

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

Użycie jest proste:

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

W Menedżerze:

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();
}
 1
Author: Andrei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-08 11:52:46

Nie Nie można przekazać parametrów do metody run(). Podpis mówi, że (nie ma parametrów). Prawdopodobnie najprostszym sposobem na to jest użycie specjalnie zbudowanego obiektu, który pobiera parametr w konstruktorze i przechowuje go w końcowej zmiennej:

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

Gdy to zrobisz - musisz uważać na integralność danych obiektu, który PRZEKAZUJESZ do "WorkingTask". Dane będą teraz istnieć w dwóch różnych wątkach, więc musisz upewnić się, że jest Bezpieczny wątek.

 1
Author: Mihir Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-13 12:00:01

Utwórz zmienną lokalną w swojej klasie, która extends Thread lub implements 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;
    }}

W ten sposób możesz przekazać zmienną podczas jej uruchamiania.

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

Wyjście:

"www.google.com"
 0
Author: calthecoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-19 13:22:32