Java 管道流 :Android 线程间通信的另一种选择
2022-04-27 本文已影响0人
Sand哥
不为别的,为了卷面试官也要看看...
PipedInputstream 和 PipedOutputStream 是Java1.1 时代就有的线程间通信API,但似乎是很少被提及,或许是其使用到的场景比较少,而且线程间通信方案简直太多了....
在Android领域这个API被保留了下来,同样你可以用它来干Handler的事情,使用的一般步骤如下
- 初始化管道
- 连接管道
- 在各自的线程种开启通信
优点:
1.流程化的过程,能轻易找到数据两端,Handler则是到处都可以send
2.看起来可以传送任何数据,包括大块流式数据,二进制数据等(谁不能,我根本不用传,共享不行么)
缺点:
使用比较麻烦,而且PipedOutputStream内部还要多开2个线程,一个读,一个写,并且应用层面还要多开线程,一个读写功能可能至少都要开3个线程,开销比较大....
总结:
没什么太大用处,纯粹是"茴"的另一种写法...
演示
以下演示如何接受子线程发送的数据然后更新到主线程中
public class Demo2MainActivity extends AppCompatActivity {
private TextView textViewLabel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo2_main);
textViewLabel = findViewById(R.id.textViewLabel2);
setTitle("Java管道流用户Android线程间通信");
//1.初始化管道
PipedInputStream pins = new PipedInputStream();
PipedOutputStream pouts = new PipedOutputStream();
try {
pins.connect(pouts);//2.连接管道
} catch (Exception e) {
e.printStackTrace();
}
//====================各自线程种执行数据收发============
//3.开启子线程,子线程发法消息到主线程
new SubThread(pouts, new WeakReference<>(this)).start();
//4.接收到子线程发出来的数据,更新到主线程UI
new Thread(() -> {
byte[] buf = new byte[512];
while (true) {
int ret = 0;
try {
ret = pins.read(buf);
} catch (IOException e) {
e.printStackTrace();
}
String received = new String(buf, 0, ret);
textViewLabel.post(() -> textViewLabel.setText("主线程接到的子线程数据:\n" + received));
}
}).start();
}
/**
* 在子线程中不断向主线程发消息
*/
public static class SubThread extends Thread {
public SubThread(PipedOutputStream pipedOutputStream, WeakReference<Activity> activityWeakReference) {
super(() -> {
while (true) {
if (null == activityWeakReference.get() || activityWeakReference.get().isFinishing()) {
break;
}
try {
if (null != pipedOutputStream) {
pipedOutputStream.write(("子线程名:" + Thread.currentThread().getName() + " 数据:" + System.currentTimeMillis() + "\n").getBytes(StandardCharsets.UTF_8));
}
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
}