有人可以向我建议如何将参数传递给线程吗?
另外,它如何用于匿名类?
答案 0 :(得分:343)
您需要将构造函数中的参数传递给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();
答案 1 :(得分:102)
在回答问题编辑时,这里是如何为匿名类
工作的 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
答案 2 :(得分:40)
通过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();
}
答案 3 :(得分:18)
这个答案来得很晚,但也许有人会觉得它很有用。它是关于如何将参数传递给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();
所有这些都发生在初始化程序块内。
答案 4 :(得分:16)
创建线程时,需要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方法:
public void setMyParam(String value){
this.myParam = value;
}
一旦你有了这个,你可以通过这样调用来改变参数的值:
myRunnable.setMyParam("Goodbye World");
当然,如果您想在参数更改时触发操作,则必须使用锁定,这会使事情变得更加复杂。
答案 5 :(得分:9)
要创建线程,通常可以创建自己的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);
}
}
答案 6 :(得分:8)
您可以扩展Thread
class
或Runnable
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();
答案 7 :(得分:7)
编写一个实现Runnable的类,并在适当定义的构造函数中传递您需要的任何内容,或编写一个使用适当定义的构造函数扩展Thread的类,该构造函数使用适当的参数调用super()。
答案 8 :(得分:5)
从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();
答案 9 :(得分:3)
您可以从Runnable派生一个类,并在构造期间(比方说)传递参数。
然后使用Thread.start(Runnable r);
启动它如果你的意思是而线程正在运行,那么只需在调用线程中保存对派生对象的引用,并调用适当的setter方法(在适当的地方进行同步)
答案 10 :(得分:3)
通过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);
}
答案 11 :(得分:2)
有一种将参数传递给runnables的简单方法。 代码:
public void Function(final type variable) {
Runnable runnable = new Runnable() {
public void run() {
//Code adding here...
}
};
new Thread(runnable).start();
}
答案 12 :(得分:2)
在Java 8中,您可以将lambda
表达式与Concurrency API& ExecutorService
作为直接使用线程的更高级替代品:
newCachedThreadPool()
创建一个创建新线程的线程池 根据需要,但会重用以前构造的线程 可用。这些池通常会提高执行许多短期异步任务的程序的性能。
private static final ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
myFunction(myParam1, myParam2);
});
另请参阅executors
javadocs。
答案 13 :(得分:1)
另一个选择;这种方法允许您像使用异步函数调用一样使用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的完成。你可以传回一个电话或者等待线程'等等。
答案 14 :(得分:1)
我知道我已经晚了几年,但是我遇到了这个问题,并采取了非正统的方法。我想不上新课就去做,所以这就是我想出的:
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();
答案 15 :(得分:1)
不,您无法将参数传递给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'的对象的数据完整性。数据现在将存在于两个不同的线程中,因此您必须确保它是线程安全的。
答案 16 :(得分:1)
对于回调目的,我通常使用输入参数实现我自己的通用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();
}
答案 17 :(得分:0)
在您的班级中创建一个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"
答案 18 :(得分:0)
首先我想指出其他答案是正确的。 但是,在构造函数中使用参数对你们所有人来说可能不是最好的主意。
在许多情况下,您会希望使用“匿名内部类”,并覆盖 run()
方法,因为为每次使用定义特定类是痛苦的。
(new MyRunnable(){...}
)
并且在您创建该 Runnable 时,您可能无法使用该参数将其传递到构造函数中。例如,如果您将此对象传递给一个方法,该方法将在单独的线程中执行一些工作,然后调用您的可运行对象,并将该工作的结果应用于它。
在那种情况下,使用这样的方法:
public MyRunnable withParameter(Object parameter)
,可能会成为更有用的选择。
我不认为这是问题的最佳解决方案,但它可以完成工作。