如何从Android / Java中的两个不同线程写入/读取字符串数据

时间:2017-07-18 20:50:04

标签: java android string multithreading

我有一个Android应用程序,它从线程A中的BLE设备接收ASCII字符串(因此字符串中的每个字符恰好对应一个字节)。

这些字符串有最大长度的块。例如,假设最大长度为4,我们收到以下字符串:

" ABCD" (4)," EFGH" (4)," I \ r \ n" (3)

另一方面,我有另一个线程B需要读取这些字符串,但作为一个完整的行。在该示例中,在接收到所有三个数据包之后,该线程应该读取一行:

" ABCDEFGHI"

我的第一个赌注是使用公共底层BlockingQueue实现自定义InputStream和OutputStream。然后使用OutputStreamWriter写入线程A中的传入字符串和包装在BufferedStream中的InputStreamReader,以使用线程B中的readLine()函数,但它不起作用。

我可以看到在线程A上使用自定义OutputStream时,字节(块)被添加到队列中但是当我从线程B调用readLine()时,它会阻塞并且永远不会返回字符串,即使我知道整行已经已添加到基础队列。

我非常确定我在这里重新发明轮子,而且我一直无法在网上找到明确的答案。必须有更好的方法在Java / Android中执行此操作。这听起来像是一种非常常见的模式。

我主要在C#做事,所以可能会有一些我缺少的课程。我也看了看ByteBuffer,但似乎这样做迫使我实现自己的readLine()函数,因为BufferedReader等没有使用的InputStream。

2 个答案:

答案 0 :(得分:0)

您可以使用 Greenrobot's EventBus 轻松地在线程之间发送数据。

Greenrobot的EventBus是一个允许组件(活动,片段,服务和背景线程)之间进行通信的库。

的build.gradle

dependencies {      
    compile 'org.greenrobot:eventbus:3.0.0'     
}

<强> 1。听众(主题A)

public class BleListener{
    private static Context _context;
    private static BleListener _instance;
    private static ListenerThread _listenerThread;
    private static boolean _isListenerThreadEnable = false;

    private BleListener(Context context){
        _context = context;

        // set ble config and open ble port in here
        // ....

        // enable listener thread
        if (!_isListenerThreadEnable) {
             _listenerThread = new ListenerThread();
             _listenerThread.start();
             _isListenerThreadEnable = true;
        }

    }

    // call this function from outer class
    public static BleListener getInstance(Context context) {
        if (_instance == null) {
            _instance = new BleListener(Context context);
        }
        return _instance;
    }

    private class ListenerThread extends Thread {

        ListenerThread() {
            // setting your receive buffer, thread priority in here
        }

        @Override
        public void run() {

            while (_isListenerThreadEnable) {
                synchronized (_bleDevice) {

                    int _receivedCount = _bleDevice.getQueueStatus();

                    while (_receivedCount > 0) {
                        // append your received data in here with ByteBuffer or StringBuffer
                        // ..

                        // parsing data for get valid data
                        // ..

                        // send valid data out when receive special character (end of message flag) or when timeout received with EventBus
                        EventBus.getDefault().post( ValidModal);                    
                    }
                }
                Thread.Yield();
           }
       }
    }
}

<强> 2。 MAIN(线程B - 从线程A读取数据)

订户还需要在总线上注册和注销。只有在订阅者注册时,他们才会收到活动。在Android中,在活动和片段中,您通常应该根据其生命周期进行注册。对于大多数情况,onStart / onStop工作正常:

@Override
public void onStart() {
    super.onStart();


    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);

    super.onStop();
}

订阅者实现在发布事件时将调用的事件处理方法(也称为“订阅者方法”)。这些是使用@Subscribe注释定义的。

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(ValidModal) {
    // You will get valid data from thread A here.
    //..
}

答案 1 :(得分:0)

根据Ted Hopp的推荐,我最终使用了 PipedInputStream PipedOutputStream (包含在OutputStreamWriter和BufferedReader中)。

它像魅力一样,完全符合我的需要。谢谢!