Runnable 实例化 Java

Runnables Instantiation Java

我正在尝试像 Executors.newFixedThreadPool 中那样编写一个 ExecutorService,并将 运行nable 作为参数提供给填充 ThreadPool 的方法。

这不是关于实例化一个内部 class 就像这里提议的 How to instantiate inner class with reflection in Java? 我实际上想要一个使用反射的替代方法。

线程池要运行的Runnable是一个抽象运行ner的实例。由于以下原因导致的错误,我无法使用 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();
    }

有更好的方法吗?

不清楚,你到底想做什么。如果你想做与你的问题相同但没有反思的事情,你可以简单地做

public void doStuff() {
    for (int i = 0; i < 10; i++) {
        doMoreStuff(new MyRunner());
    }
}

public void doMoreStuff(TestRunner t) {
    new Thread(t).start();
}

因为这就是您在问题代码中实际做的事情,它也与您在 中编写的内容相匹配:“我想通过将 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();
}