17 ответов:
вам нужно передать параметр в конструкторе в объект 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();
для анонимных классов:
в ответ на вопрос правки, как это работает для анонимных классов
final X parameter = ...; // the final is important Thread t = new Thread(new Runnable() { p = parameter; public void run() { ... }; t.start();
именованные классы:
у вас есть класс, который расширяет поток (или реализует Runnable) и конструктор с параметрами, которые вы хотите передать. Затем, когда вы создаете новый поток, вы должны передать аргументы, а затем запустить поток, что-то вроде этого:
Thread t = new MyThread(args...); t.start();Runnable-это гораздо лучшее решение, чем Нить кстати. Поэтому я бы предпочел:
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();этот ответ в основном такой же, как и этот аналогичный вопрос: как передать параметры объекту потока
через конструктор класса 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(); }
когда вы создаете поток, вам нужен экземпляр
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");конечно, если вы хотите вызвать действие при изменении параметра Вам придется использовать блокировки, что значительно усложняет задачу.
этот ответ приходит очень поздно, но, может, кто-то найдет его полезным. Речь идет о том, как передать параметр(ы) к
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();так что все происходит внутри блока инициализатора.
чтобы создать поток, вы обычно создаете свою собственную реализацию 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); } }
вы можете либо продлить
ThreadclassилиRunnableclassи обеспечить параметры, как вы хотите. Есть простые примеры в 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();
либо напишите класс, который реализует Runnable, и передайте все, что вам нужно в подходящем определенном конструкторе, либо напишите класс, который расширяет поток с соответствующим определенным конструктором, который вызывает super() с соответствующими параметрами.
начиная с Java 8, вы можете использовать лямбда для захвата параметров, которые эффективно окончательной. Например:
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, и во время построения (скажем) передать параметр.
затем запустите его с помощью резьбы.start (Runnable r);
Если вы имеете в виду пока поток запущен, а затем просто держите ссылку на производный объект в вызывающем потоке и вызывайте соответствующие методы setter (синхронизация там, где это необходимо)
параметр, проходящий через методы 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); }
есть простой способ передачи параметров в runnables. Код:
public void Function(final type variable) { Runnable runnable = new Runnable() { public void run() { //Code adding here... } }; new Thread(runnable).start(); }
в Java 8 вы можете использовать
lambdaвыражения с API параллелизма иExecutorServiceкак замена более высокого уровня для работы с потоками напрямую:
newCachedThreadPool()создает пул потоков, который создает новые потоки по мере необходимости, но будет повторно использовать ранее созданные потоки, когда они доступный. Эти пулы, как правило, повышают производительность программ, выполняющих множество краткосрочных асинхронных задач.private static final ExecutorService executor = Executors.newCachedThreadPool(); executor.submit(() -> { myFunction(myParam1, myParam2); });посмотреть также
executorsjavadocs.
еще один вариант; этот подход позволяет использовать работоспособного элемента как асинхронный вызов функции. Если вашей задаче не нужно возвращать результат, например, она просто выполняет какое-то действие, вам не нужно беспокоиться о том, как вы возвращаете "результат".
этот шаблон позволяет повторно использовать элемент, где вам нужно какое-то внутреннее состояние. Когда не передается параметр (ы) в конструкторе уход необходим, чтобы опосредовать доступ программ к параметрам. Вам может понадобиться больше проверок, если ваш use-case включает в себя разные абоненты и т. д.
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 (параметр)); Т.начать();
Если вам нужен результат обработки, вам также нужно будет координировать завершение MyRunnable, когда подзадача завершится. Вы можете передать обратный вызов или просто подождать в потоке 't' и т. д.
специально для Android
для целей обратного вызова я обычно реализую свой собственный generic
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(); }
нет, вы не можете передать параметры
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". Теперь данные будут существовать в двух разных потоках, поэтому вы должны убедиться, что это поток Безопасный.
создайте локальную переменную в своем классе, которая
extends Threadили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; }}таким образом, вы можете передать переменную при ее запуске.
Extractor e = new Extractor("www.google.com"); e.start();вывод:
"www.google.com"
Comments