Java 是否可以使用参数运行?
我需要一个“接受参数的Runnable”,尽管我知道这种Runnable实际上并不存在 这可能指向我的应用程序设计中的根本缺陷和/或我疲惫的大脑中的心理障碍,因此我希望在这里找到一些建议,说明如何在不违反基本OO原则的情况下完成以下工作:Java 是否可以使用参数运行?,java,runnable,Java,Runnable,我需要一个“接受参数的Runnable”,尽管我知道这种Runnable实际上并不存在 这可能指向我的应用程序设计中的根本缺陷和/或我疲惫的大脑中的心理障碍,因此我希望在这里找到一些建议,说明如何在不违反基本OO原则的情况下完成以下工作: private Runnable mOneShotTask = new Runnable(String str) { public void run(String str) { someFunc(str); } };
private Runnable mOneShotTask = new Runnable(String str) {
public void run(String str) {
someFunc(str);
}
};
你知道如何实现上述功能吗?自从我最初发布这篇文章以来,已经将近9年了,老实说,Java从那时起已经做了一些改进。我将在下面留下我的原始答案,但人们没有必要做其中的事情。9年前,在代码审查期间,我会质疑他们为什么这么做,可能会批准,也可能不会。在现代Lambda可用的情况下,在现代Java中,有如此高投票率的答案推荐一种过时的方法(公平地说,这种方法一开始是可疑的…)是不负责任的,代码审查将立即被拒绝,建议:
void foo(final String str) {
Thread t = new Thread(() -> someFunc(str));
t.start();
}
和以前一样,以有意义的方式处理该线程之类的细节留给读者作为练习。但坦率地说,如果你害怕使用lambdas,你应该更害怕多线程系统
最初的答案,只是因为:
您可以在方法中声明类权限
void Foo(String str) {
class OneShotTask implements Runnable {
String str;
OneShotTask(String s) { str = s; }
public void run() {
someFunc(str);
}
}
Thread t = new Thread(new OneShotTask(str));
t.start();
}
您有两个选择:
最终版
我首先想知道您在这里想要完成什么,以便需要将参数传递给new Runnable()或run()。
通常的方法应该是让一个可运行对象在启动之前通过设置成员变量将数据(str)传递给它的线程。然后run()方法使用这些成员变量值来执行someFunc()您可以将其放入函数中
String paramStr = "a parameter";
Runnable myRunnable = createRunnable(paramStr);
private Runnable createRunnable(final String paramStr){
Runnable aRunnable = new Runnable(){
public void run(){
someFunc(paramStr);
}
};
return aRunnable;
}
(当我使用此参数时,我的参数是一个整数ID,我用它来生成ID-->myRunnables的hashmap。这样,我可以使用hashmap在处理程序中发布/删除不同的myRunnable对象。)
创建一个init函数,返回对象本身并用它初始化参数。我使用以下实现接口的类。使用这个类,您可以轻松地创建带有参数的新线程
public abstract class RunnableArg implements Runnable {
Object[] m_args;
public RunnableArg() {
}
public void run(Object... args) {
setArgs(args);
run();
}
public void setArgs(Object... args) {
m_args = args;
}
public int getArgCount() {
return m_args == null ? 0 : m_args.length;
}
public Object[] getArgs() {
return m_args;
}
}
自Java 8以来,最好的答案是使用
消费者
:
它是函数接口之一,这意味着您可以将其作为lambda表达式调用:
void doSomething(Consumer<String> something) {
something.accept("hello!");
}
...
doSomething( (something) -> System.out.println(something) )
...
void doSomething(消费者某物){
接受(“你好!”);
}
...
doSomething((某物)->System.out.println(某物))
...
谢谢大家!所有建议的解决方案都指向相同的方法,但我只能接受其中一种。我一定很累了,因为我自己不能想出这个办法+事实上,大多数人不知道你可以在一个方法中声明一个类。有些人会认为这是一种很差的风格。我想这是品味的问题公共接口ResultRunnable{public void run(T result);}@Massa:请参阅感谢分享代码-我喜欢人们这样做,而不仅仅是喋喋不休。一个问题-当涉及内存泄漏时,上述方法是否可行?你通过的所有推荐信都会被妥善处理?@kape123答案是“视情况而定”。只要该方法返回的Runnable
对象存在于任何位置,则paramStr
可能不符合垃圾收集的条件。如果对象存在但无法再次运行,JIT(甚至javac)可能会决定将其从范围中删除,但我们不应该依赖这些优化,因为它们可能会在将来发生变化。“感谢共享代码-我喜欢人们这样做,而不只是喋喋不休。”-什么?@RobGrant真正的讽刺是,在那之后,他们于是特别要求说废话!!哦,他们只想听到他们需要的那些废话?明白了。您如何使用这个抽象类来运行带有参数的runnable?我更喜欢使用带有参数的构造函数public RunnableArg(Object…args){setArgs(args);}
然后描述本地类:class ActionArg扩展RunnableArg{public ActionArg(Object…arg){super(arg);}@Override public void run(){/*getArgs()并处理它们*/}
并使用它Thread t=new Thread(new ActionArg(%param_object)%);t.start();
很遗憾,您将无法将其分配给变量并调用init()现在,您可以使用消费者
。我已经阅读了这个问题的各种答案。似乎有点奇怪,没有人告诉您可以向项目中添加所需的可运行程序(带有一个、两个、三个或更多参数),只需添加适当的接口即可。我在这里为感兴趣的人创建了一个注释要点:这不是重复的“如何将参数传递给Java线程”,现代的答案是,如@Alex78191所说:使用消费者
void doSomething(Consumer<String> something) {
something.accept("hello!");
}
...
doSomething( (something) -> System.out.println(something) )
...