简体   繁体   中英

Elegant way to transform Multi-thread into Single-thread

1. I have main UI thread and it uses library functions.

MainUI {
    library.funcA(1);
    library.funcB(2,3);
}

I don't want Main-Thread to wait for the end of each call. Also creating new thread for each call is ineffective and not thread-safe so I want them to run on another same thread. So I created another thread with a single message queue / handler.

MainUI {
    handler.post(new Message(FUNC_A,[1]));
    handler.post(new Message(FUNC_B,[2,3]));
}

but it seems having overhead that I need to create new Message object every time and decode it again in handleMessage(). Furthermore It looks ugly to handle the various number of arguments packing/unpacking. I thought making all functions as Runnable and post them to handler, but functions have different arguments and I need to make new classes extending Runnable class!

my current plan is to insert synchronized keywords into every function in library so threads run one by one, but I dislike many threads creating/disappering so making system heavy (also not thread-safe). I want to hear opinions.

2. if the library is called from many threads (not only Main-thread), what's the best way to convert calls to run on the library's own single thread?

In my opinion, your current approach is feasible option to make thread-safe. However, if you want to go for having Runnable passed to handler, you could consider overloading your Runnable class. Here is pseudo-code

private Class MyRunner extends Runnable{
    public MyRunner(){
    //This is without any argument
    }

    public MyRunner(arg1){
    //This is with 1 argument
    }

    public MyRunner(arg1,arg2){
    //This is with 2 arguments
    }

}

Still, you will have many instances of MyRunner class created.

You can use a Runnable like this:

int x = 1;
int y = 2;
//  "a" and "b" are here to show how variable values can be sent to funcB.
//  You could skip this and just have "funcB( 1, 2 )", of course.
final int  a = x;  
final int  b = y;
handler.post( new Runnable()  {
    public void run()  { library.funcB( a, b ); }
} );

The handler bit is a bit trickier. It has to run a looping thread to run each Runnable from the queue. Then it has to have a post method to put things on the queue. Some form of blocking queue would be the simplest way to link the two, saving you from having to do your own Object.wait/Object.notify. Synchronizing the post method would be the easiest way to keep multiple threads from tripping over each other.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM