我正在尝试在ExecutorService
中编写一个Executors.newFixedThreadPool
,其中一个runnable作为填充ThreadPool
的方法的参数。
这不是关于实例化像这里提出的内部类How to instantiate inner class with reflection in Java?我实际上想要使用反射的替代方法。
线程池运行的Runnable
是抽象运行器的实例。由于以下原因导致的错误,我无法使用testRunnable.newInstance()
或testRunnable::new
创建实例。
java.lang.NoSuchMethodException:... $ MyRunner。()exception。
现在我通过反思这样做:
public void doStuff() throws Exception {
MyRunner r = new MyRunner();
for (int i = 0; i < 10; i++) {
doMoreStuff(r.getClass(), this);
}
}
public void doMoreStuff(Class<? extends TestRunner> clazz, Object... params) throws Exception {
Class<?>[] types = Stream.of(params).map(Object::getClass).toArray(n -> new Class[n]);
TestRunner t = clazz.getConstructor(types).newInstance(params);
new Thread(t).start();
}
有更好的方法吗?
答案 0 :(得分:1)
目前尚不清楚,你真正想做什么。如果你想在你的问题中做同样的事情,但没有反思,你可以简单地做到
public void doStuff() {
for (int i = 0; i < 10; i++) {
doMoreStuff(new MyRunner());
}
}
public void doMoreStuff(TestRunner t) {
new Thread(t).start();
}
因为这就是你在问题代码中实际做的事情,它也与你在your comment中所写的内容相符:“我希望通过将runnable的不同特化传递给doMoreStuff()
来减少重复代码方法”。您可以将TestRunner
的任意特化传递给方法doMoreStuff
...
似乎您希望在方法doMoreStuff()
内而不是在调用者处执行新实例的创建,尽管您的问题没有提供有关为什么的任何提示。如果有正当理由,你可以这样做:
public void doStuff() {
for (int i = 0; i < 10; i++) {
doMoreStuff(MyRunner::new);
}
}
public void doMoreStuff(Supplier<? extends TestRunner> s) {
new Thread(s.get()).start();
}
尽管做出类似的事情会更自然:
public void doStuff() {
doMoreStuff(MyRunner::new);
}
public void doMoreStuff(Supplier<? extends TestRunner> s) {
for(int i = 0; i < 10; i++)
new Thread(s.get()).start();
}
这确实将“十次”执行策略与执行执行决策分开。
如果您的问题源于尝试允许将外部实例作为参数提供,那么这不适用于::new
方法引用,因为它们总是将外部实例视为隐含和预绑定。在这种情况下,你必须求助于lambda表达式:
public void doStuff() {
doMoreStuff(outer -> outer.new MyRunner(), this);
}
public <T> void doMoreStuff(Function<T,? extends TestRunner> s, T context) {
for(int i = 0; i < 10; i++)
new Thread(s.apply(context)).start();
}