谁能建议我如何将参数传递给线程?
另外,它如何用于匿名类?
Consumer<T>
。
谁能建议我如何将参数传递给线程?
另外,它如何用于匿名类?
Consumer<T>
。
Answers:
您需要将构造函数中的参数传递给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();
r
将具有相同的参数,因此,如果我们要将不同的参数传递给正在运行的多个线程,则需要为每个线程使用所需的参数MyThread
创建一个新MyThread
实例。换句话说,要启动和运行线程,我们需要创建两个对象:Thread和MyThread。从性能角度来看,这被认为是不好的吗?
在回应问题编辑时,这是匿名类的工作方式
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();
这个答案与这个类似的问题基本相同:如何将参数传递给Thread对象
parameter
直接从run()
方法访问而p
根本不使用任何字段。似乎有效。是否有一些我没有事先复制parameter
到的微妙的多线程东西p
?
)
在第一个例子
final X parameter
在new Runnable()
生产线前有,我就可以进入parameter
内部run()
。我不需要做额外的事情p = parameter
。
final
不再那么重要了;变量有效地为最终变量就足够了(尽管使用它没有害处)
通过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();
}
@Override
?
@Override
明确声明它正在覆盖Thread类中的抽象方法。
这个答案来得很晚,但是也许有人会觉得有用。它是关于如何在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();
因此,所有操作都发生在初始化程序块内部。
this.myParam
那真的必要吗?您不能只删除私有变量并从外部范围引用该变量吗?我理解(当然),这有一些含义,例如,在启动线程后可以更改变量。
创建线程时,您需要一个实例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");
当然,如果要在更改参数时触发操作,则必须使用锁,这会使事情变得更加复杂。
您可以扩展或并根据需要提供参数。在docs中有简单的示例。我将它们移植到这里:Thread
class
Runnable
class
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();
在Java 8中,您可以将lambda
表达式与Concurrency API配合使用,并ExecutorService
作为高级替换直接使用线程:
newCachedThreadPool()
创建一个线程池,该线程池根据需要创建新线程,但是将在先前构造的线程可用时重用它们。这些池通常将提高执行许多短期异步任务的程序的性能。
private static final ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
myFunction(myParam1, myParam2);
});
另请参见executors
javadocs。
通过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);
}
不,您不能将参数传递给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'的对象的数据完整性。数据现在将存在于两个不同的线程中,因此您必须确保它是线程安全的。
另一种选择;这种方法使您可以像异步函数调用一样使用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 = new Thread(new MyRunnable(parameter)); t.start();
如果需要处理结果,则还需要在子任务完成时协调MyRunnable的完成。您可以回拨电话,也可以等待线程“ t”等。
为了回调,我通常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();
}
创建你的类,一个局部变量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"