Runnables Instantiation Java

时间:2015-11-25 16:12:09

标签: java java-8 strategy-pattern

我正在尝试在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();
    }

有更好的方法吗?

1 个答案:

答案 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();
}