今天遇到一个线程相关的有趣情况:
发布者-订阅者模式中,(订阅者的)onNext和(订阅<Subscription>的)request之间反复调用导致爆栈(stackoverflow),解决方法之一是把订阅的request放到另一个线程里运行。
这个问题的细节还没有搞通,但大体情况是理解了:两个函数/程序片段互相goto,每goto一次还要记录之前的情况和返回位置。
我做了一个最小可复现代码:
第一部分:爆栈情况
public static void main(String... args) {
fun1("hi");
}
public static void fun1(String in1){
System.out.println(in1);
fun2(" 1 ");
}
public static void fun2(String in2){
System.out.println(in2);
fun1(" 2 ");
}
第二部分:两个进程顺利运行情况
static ExecutorService executor =
Executors.newSingleThreadExecutor();
public static void main(String... args) {
fun1("hi");
}
public static void fun1(String in1){
System.out.println(in1);
fun2(" 1 ");
}
public static void fun2(String in2){
executor.submit(()->{
System.out.println(in2);
fun1(" 2 ");
});
}
这个例子与本帖原初话题有什么关系呢?首先它从一个角度增强了我对线程的重视,线程优先级问题自然也就更重要了。其二,本例涉及的是最基本、非堵塞的情况,而实际中难免甚至一定情况下推荐采用堵塞的情况,增加了死锁等情况的风险,在这种情况下线程优先级是非常重要的一个问题,通过确定优先级来尽可能理顺关系。
参考:
Modern Java in Action, chapter 17.2.2