为类的任何函数编写可线程包装器?

时间:2016-08-22 03:21:09

标签: java android multithreading sqlite

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

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

或者有没有办法制作一个通用的线程/回调函数来接受你给它的任何函数并以这种方式处理它?<​​/ p>

2 个答案:

答案 0 :(得分:0)

问题是:java没有允许你使用任何函数的含义。

因此,在java之前,您通常会传递Runnable的某个实例或使用ExecutorService传递Callables

使用Java8,您可以与functional interfaces一起查看method references

长话短说。你可以创建一些带有一些“void *”指针的代码,就像在C的好日子里一样;但你有几个选择如何接近它。

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

答案 1 :(得分:0)

您可以使用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或您界面中方法的名称。然后,您可以在代理的invoke方法中使用注释。确保您的注释具有保留Runtime