我有一个可以通过NDK访问的C库。某些操作非常耗时,因此UI线程会冻结它们。我现在常见的做法是使用Runnable:
myFixedThreadPool.execute(new Runnable()
{
public void run()
{
NativeClass.callToNDKLibrary();
};
});
或类似的线程:
Thread t = new Thread()
{
public void run()
{
NativeClass.callToNDKLibrary();
}
};
t.start();
但问题是C库不是线程安全的:当我像这样包装它时会开始崩溃。所以问题是如何从UI线程分离仍然强制NDK调用一次运行一个。可能是同步的一些技巧会有帮助吗?我还想提一下,这个库是我的应用程序的核心底层,而不仅仅是一个辅助函数。所以它几乎从我的代码的每个部分调用。并且只有少数函数消耗时间,大多数函数很快将它们保存在主线程中。
答案 0 :(得分:3)
最终解决方案如下:
定义单线程执行程序:
ExecutorService mExecutorThread = Executors.newSingleThreadExecutor();
在该线程中包装所有耗时的操作:
mExecutorThread.execute(new Runnable() { public void run() { NativeClass.callToNDKLibrary(); } });
我必须做的最后一件事是稍微重新设计我的代码,以确保没有从onDraw()调用任何本机方法。我在事件处理程序中缓存了本机方法的结果,并在onDraw()中使用了缓存的值。
答案 1 :(得分:2)
但问题是C库不是线程安全的:当我像这样包装它时会开始崩溃。
然后对库中的所有操作使用单个专用后台线程。例如,使用IntentService
访问库,调用startService()的活动将命令发送到IntentService
。
或者:
LinkedBlockingQueue<Job>
类/接口创建Job
或者,花时间在C级别使库具有线程安全性。使C代码成为线程安全的问题已经讨论了大约20年,因此可能会有一些技巧可以使用来自所有这些经验。
答案 2 :(得分:0)