2.1 Thread Communication -- Pipe

Android中的线程间通信一般使用Handler-Looper机制,而我们也可以使用Java中的方式来实现线程间通信。

Pipe(管道)

一个管道为两个线程在同一个进程中提供了一条通道,然后连接并建立一个单方向的通道。在这个通道上,一个生产者线程写数据到管道中,另一个消费者线程从管道中读数据。


在Linux中,Pipe operator是跨进程工作的,而在Java中虚拟机中跨线程工作的(在同一个进程中)。


Pipe简介

工作流程

  1. 在内存中分配一块环形缓冲器;
  2. 只有两个连接上的线程可以访问缓冲器,其他线程无法访问到数据,因此确保了线程安全;
  3. 管道是单方向的,确保了一个写,另外一个读。
    这里写图片描述

传输的数据类型

管道可以传输字节数据(binary-二进制数据)和字符数据(character)。
字节数据使用的类:
PipedOutputStream - 生产者
PipedInputStream - 消费者
字符数据使用的类:
PipedWriter - 生成者
PipedReader - 消费者

声明周期

无论是写线程还是读线程建立了连接,那么就是管道生命周期开始的时候;当这个连接关闭的时候,就是管道生命周期结束的时候。

Pipe的基本使用

管道的生命周期可以分为3步:建立连接,传输数据,断开连接。

1. 建立连接

PipedReader r = new PipedReader();
PipedWriter w = new PipedWriter();
w.connect(r);

默认的缓存大小是1024,我们可以在通道的消费者端设置这个缓存大小。

int BUFFER_SIZE_IN_CHARS = 1024 * 4;
PipedReader r = new PipedReader(BUFFER_SIZE_IN_CHARS);
PipedWriter w = new PipedWriter(r);

2.把Reader放入处理线程中

把reader传到一个处理的线程中,然后reader线程开启后,就开始从writer那儿接收数据。

Thread t = new MyReaderThread(r);
t.start();

3. 传输数据

// 生成者线程:写入数据
w.write('ABC');
// 消费者线程:读取数据
int result = r.read();

因为生成者可能会写满或者消费者可能读取不到数据,那么就会阻塞。下面的写法更好。

// 生产者线程:写入数据后,flush管道
w.writer('ABC');
w.flush();

// 消费者线程:在一个判断循环中读取数据
int i;
while((i = reader.read()) != -1) {
    char c = (char) i;
    // TODO
}

调用flush()方法会通知消费者线程有新的数据可以读取,这样可以减少消费者线程的等待时间。

4.关闭连接

当数据传输完后要关闭通道。

// 生成者线程:关闭writer
w.close();
// 消费者线程:关闭reader
r.close();

如果writer和reader已经建立连接,那么关闭其中一个也是足够的。如果writer关闭,管道就会断开连接,但是缓存的数据仍然可以被读取到;如果reader关闭,那么缓存区会被清空。因此writer和reader要都关闭。

Demo

public class PipeActivity extends Activity {

    private static final String TAG = PipeActivity.class.getSimpleName();
    private EditText pipeEdit = null;

    private PipedWriter writer = null;
    private PipedReader reader = null;

    private Thread readerThread = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pipe);

        writer = new PipedWriter();
        reader = new PipedReader();

        try {
            writer.connect(reader);
        }
        catch (IOException e) {
            e.printStackTrace();
        }

        pipeEdit = (EditText) findViewById(R.id.pipe_edit);
        pipeEdit.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
                try {
                    if (count > before) {
                        writer.write(charSequence.subSequence(before, count).toString());
                        writer.flush();
                    }
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

        readerThread = new Thread(new TextHandlerRunable(reader));
        readerThread.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        readerThread.interrupt();
        try {
            writer.close();
            reader.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static class TextHandlerRunable implements Runnable {
        private final PipedReader reader;

        public TextHandlerRunable(PipedReader reader) {
            this.reader = reader;
        }

        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    int i;
                    while ((i = reader.read()) != -1) {
                        char c = (char) i;
                        Log.i(TAG, "read: " + c);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值