开发者

How to solve the problem of NDK library calls freezing UI thread

开发者 https://www.devze.com 2023-01-22 20:40 出处:网络
I have a C library which I access through NDK. Some operations are time consuming so UI thread freezes on them. As I now the common practice is to use Runnable like that:

I have a C library which I access through NDK. Some operations are time consuming so UI thread freezes on them. As I now the common practice is to use Runnable like that:

myFixedThreadPool.execute(new Runnable() 
{
  public void run() 
  {
    NativeClass.callToNDKLibrary();
  };
});

or threads like that:

Thread t = new Thread() 
{
  public void run() 
  {
    NativeClass.callToNDKLibrary();
  }
};
t.start();  

but the problem is that C library is not thread safe: it starts to crash when开发者_开发问答 I wrap it like this. So the question is how to detach from UI thread still enforcing NDK calls to run one at a time. May be some trick with synchronized will help? I also want to mention that this library is a core underlying layer for my application, not just a helper function. So it's called from nearly every part of my code. And only a few functions consume time, most a quick to keep them in main thread.


The final solution is as follows:

  1. Define all JNI native methods as synchronized. This will prevent C library from crashing but still will freeze UI.
  2. Define single thread executor:

    ExecutorService mExecutorThread = Executors.newSingleThreadExecutor();

  3. Wrap all time consuming operations in that thread:

    mExecutorThread.execute(new Runnable() { public void run() { NativeClass.callToNDKLibrary(); } });

Last thing I had to do was to slightly redesign my code to make sure that none of native methods are called from onDraw(). I made the results of native methods cached in event handlers and used that cached values in onDraw().


but the problem is that C library is not thread safe: it starts to crash when I wrap it like this.

Then use a single dedicated background thread for all operations on the library. For example, use an IntentService to access the library, with the activities calling startService() to send commands to the IntentService.

Or:

  1. Create a LinkedBlockingQueue<Job>, for some Job class/interface you define
  2. Have a single thread monitor that queue
  3. Send jobs to that queue to access your library
  4. Send a special "kill job" to the queue to cause the monitor-the-queue loop to exit, causing the background thread to terminate, once you no longer need the queue and thread

Or, spend the time to make the library thread-safe at the C level. Making C code be thread-safe has been a topic of discussion for ~20 years, so there is probably some tricks you can use that have arisen from all that experience.


You could use a Looper to create a message loop. Then pass your NDK calls in via a Handler and each will be run in turn.

0

精彩评论

暂无评论...
验证码 换一张
取 消