【问题标题】:Writing a threaddable wrapper for any function of a class?为类的任何函数编写线程包装器?
【发布时间】:2016-12-28 11:57:33
【问题描述】:

在 Java 中,我有一个包含许多 SQLite CRUD 函数的类,它们都属于同一个类,SQLiteCrudHelper

让所有这些函数在 UI 线程之外运行的唯一方法是为每个 CRUD 函数编写一个包装函数,它启动一个新线程,运行 CRUD 函数,然后返回一个回调,这样你就可以实现什么完成后会发生吗?

或者有没有办法制作一个通用的线程/回调函数,该函数将采用您提供的任何函数并以这种方式对待它?

【问题讨论】:

  • 为什么不编写自己的通用包装器,例如 runOnNewThread(Runnable task, Runnable callback)
  • @JiangYD 我想这就是我要问的

标签: java android multithreading sqlite


【解决方案1】:

问题是:java 没有允许你使用 any 功能的方法。

因此,在 Java 8 之前,您通常会传递 Runnable 的一些实例或使用 ExecutorService 传递 Callables

使用Java8,您可以查看functional interfacesmethod references

长话短说。您可以像在 C 的好坏日子一样创建带有一些“void*”指针的代码;但是您有多种选择来接近它。

最后:我的“个人”选择是查看 ExecutorServices 而不是使用“裸机线程”(或线程池);因为这些可以很容易地替换为"same thread executor service",这使得将多线程代码转换回“单线程”进行单元测试变得非常容易。

【讨论】:

  • 这就是我指出函数式接口的原因:例如,使用 BiFunction 可能是合理的;并允许使用该接口的代码,并使用您自己的一些接口进行改进。
  • 我在 Java 8 之前的版本中工作,所以我认为我不能使用其中任何一个,但无论如何我都会接受答案,只是接受我可能无法在 Java 中做到这一点7
【解决方案2】:

您可以使用Proxy

如果你有这样的界面:

public interface ICL1 {

    public String foo();

    public String bar(String x);
}

还有这样的课程:

public class CL1 implements ICL1 {

    @Override
    public String foo() {
        return "foo";
    }

    @Override
    public String bar(String foo) {
        return foo + "bar";
    }

}

你可以像这样代理它:

public class TProxy<T> implements InvocationHandler {

    private final ExecutorService exe = Executors.newCachedThreadPool();

    public final Object object;

    private TProxy(T object) {
        this.object = object;
    }

    public static <U> U getProxy(Class<U> intf, U target) {
        return (U) Proxy.newProxyInstance(target.getClass().getClassLoader(), new Class[]{intf}, new TProxy(target));
    }

    @Override
    public Object invoke(Object target, Method method, Object[] args) throws Throwable {
        Future f = exe.submit(() -> method.invoke(object, args));
        return f.get();
    }

}

然后你可以像这样使用代理:

System.out.println(TProxy.getProxy(ICL1.class, new CL1()).foo());

Spring 一直都在这样做;)。享受吧。

注意:这不会处理回调。我的建议是使用您自己的自制注释来注释您的方法,其中包含对回调的一些引用,可能是另一个Runnable,或者您界面中的方法名称。然后,您可以在 Proxy 的 invoke 方法中使用注解。确保您的注释保留Runtime

【讨论】:

    猜你喜欢
    • 2018-06-29
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    • 2020-08-31
    • 2023-03-25
    • 2015-03-24
    • 2014-09-20
    • 2020-05-24
    相关资源
    最近更新 更多