ExecutorService线程在RxJava代码中未按预期工作

ExecutorService线程在RxJava代码中未按预期工作,java,rx-java,executorservice,Java,Rx Java,Executorservice,我正在RxJava代码中为调度程序线程池使用java.util.concurrent.ExecutorService: public class Test { ExecutorService poolA = newFixedThreadPool(10, threadFactory("Scheduler-A-%d")); Scheduler schedulerA = Schedulers.from(poolA); privat

我正在RxJava代码中为调度程序线程池使用java.util.concurrent.ExecutorService:

  public class Test {
        ExecutorService poolA = newFixedThreadPool(10, threadFactory("Scheduler-A-%d"));
        Scheduler schedulerA = Schedulers.from(poolA);
        private ThreadFactory threadFactory(String pattern) {
        return new ThreadFactoryBuilder()
                .setNameFormat(pattern).build();
        }
        
        @Test
        public void testSubscribeOn() {
            log("Starting");
            final Observable<String> obs = simple();
            log("Created");
            obs
                    .doOnNext(Utils::log)
                    .map(x -> x+1) 
                    .doOnNext(Utils::log)
                    .subscribeOn(schedulerA)
                    .map(x -> x+2) 
                    .doOnNext(Utils::log)
                    .subscribe( 
                         x -> log("Got " + x),
                         Throwable::printStackTrace,
                         () -> log("Completed"));
    
            log("exiting");
        }
    }
    
    public class Utils {
        private static long start = System.currentTimeMillis();
    
        public static void log(Object label) {
            System.out.println(
                    System.currentTimeMillis() - start + "\t| " +
                            Thread.currentThread().getName() + "\t| " +
                            label);
        }
    }
公共类测试{
ExecutorService poolA=newFixedThreadPool(10,threadFactory(“调度器-A-%d”);
调度程序schedulerA=调度程序。来自(poolA);
私有ThreadFactory ThreadFactory(字符串模式){
返回新的ThreadFactoryBuilder()
.setNameFormat(pattern.build();
}
@试验
public void testSubscribeOn(){
日志(“启动”);
最终可观测obs=简单();
日志(“创建”);
obs
.doOnNext(Utils::log)
.map(x->x+1)
.doOnNext(Utils::log)
.subscribeOn(附表a)
.map(x->x+2)
.doOnNext(Utils::log)
.订阅(
x->log(“得到”+x),
可丢弃::printStackTrace,
()->日志(“已完成”);
日志(“退出”);
}
}
公共类UTIL{
私有静态长启动=System.currentTimeMillis();
公共静态无效日志(对象标签){
System.out.println(
System.currentTimeMillis()-start+“\t |”+
Thread.currentThread().getName()+“\t|”+
标签);
}
}
我观察到的是,主线程在调度程序线程开始工作之前退出,因此不会显示调度程序线程的输出。据我所知,ExecutorService线程不是守护进程线程,那么为什么会出现这种行为?

Setup 我认为这与JUnit的运行程序有关。让我们看一下以下示例:

public class WhileTrueJava {
  public static void main(String[] args) {
    Thread thread =
        new Thread(
            () -> {
              while (true) {}
            });
    thread.setDaemon(false);
    thread.start();

    log("exit");
  }

  private static void log(Object msg) {
    System.out.println(Thread.currentThread().getName() + "-" + msg);
  }
}
当我运行给定的示例时,进程将不会退出。当我在JUnit中使用相同的代码时,该过程将完成。我还不能说,为什么会这样

例子: 在线程池关闭并执行所有正在运行的任务之前,进程似乎不会停止

只需添加
poolA.shutdown()
main
方法的末尾,查看发生了什么。我想说的是,这种行为和预期的一样

更新
JUnit
的行为不同,因为下面的代码^1

public static void main(String... args) {
    int exitCode = execute(System.out, System.err, args).getExitCode();
    System.exit(exitCode);
}
看起来,当主线程失败时,进程将被
System.exit
终止。因此,这是JUnit的故障


^1 JUnit Github

请将您的问题包括作为一个完整的源代码,其他人可以编译和测试这些源代码。@Progman、@sta、@Jazb,您为什么关闭此问题?看起来我可以弄清楚什么是提问,以及如何重现提问。这种行为是不能接受的。很明显,当有一个
ExecutorService
-任务正在运行时,它会询问为什么
main
线程/进程会退出。@Mandroid,我更新了这个答案。
class So65650913 {
  static ExecutorService poolA = newFixedThreadPool(10, threadFactory("Scheduler-A-%d"));
  static Scheduler schedulerA = Schedulers.from(poolA);

  public static void main(String[] args) {
    Utils.log("Starting");
    Observable<String> obs =
        Observable.fromCallable(
            () -> {
              Utils.log("fromCallable lambda called");
              Thread.sleep(1_000);
              Utils.log("fromCallable return value");
              return "42";
            });

    Utils.log("Created");

    Disposable completed =
        obs.doOnNext(Utils::log)
            .map(x -> x + 1)
            .doOnNext(Utils::log)
            .subscribeOn(schedulerA)
            .map(x -> x + 2)
            .doOnNext(Utils::log)
            .subscribe(
                x -> Utils.log("Got " + x),
                Throwable::printStackTrace,
                () -> Utils.log("Completed"));

    Utils.log("exiting");
  }

  private static ThreadFactory threadFactory(String pattern) {
    return new ThreadFactoryBuilder().setDaemon(false).setNameFormat(pattern).build();
  }
}

class Utils {
  private static final long start = System.nanoTime();

  private Utils() {}

  public static void log(Object label) {
    System.out.println(
            (System.nanoTime()
            - start) / 1_000_000
            + "\t| "
            + Thread.currentThread().getName()
            + "\t| "
            + label);
  }
}
0   | main  | Starting
62  | main  | Created
77  | main  | exiting
78  | Scheduler-A-0 | fromCallable lambda called
1078    | Scheduler-A-0 | fromCallable return value
1082    | Scheduler-A-0 | 42
1082    | Scheduler-A-0 | 421
1082    | Scheduler-A-0 | 4212
1082    | Scheduler-A-0 | Got 4212
1082    | Scheduler-A-0 | Completed
public static void main(String... args) {
    int exitCode = execute(System.out, System.err, args).getExitCode();
    System.exit(exitCode);
}