Java 主线程中的SubscribeOn和observeOn
我试图在执行器中使用subscribeOn和obsereOn,以便在异步任务完成后返回主线程。 我最终得到了这个代码,但它不起作用Java 主线程中的SubscribeOn和observeOn,java,rx-java,reactive-programming,rx-java2,Java,Rx Java,Reactive Programming,Rx Java2,我试图在执行器中使用subscribeOn和obsereOn,以便在异步任务完成后返回主线程。 我最终得到了这个代码,但它不起作用 @Test public void testBackToMainThread() throws InterruptedException { processValue(1); processValue(2); processValue(3); processValue(4); p
@Test
public void testBackToMainThread() throws InterruptedException {
processValue(1);
processValue(2);
processValue(3);
processValue(4);
processValue(5);
// while (tasks.size() != 0) {
// tasks.take().run();
// }
System.out.println("done");
}
private LinkedBlockingQueue<Runnable> tasks = new LinkedBlockingQueue<>();
private void processValue(int value) throws InterruptedException {
Observable.just(value)
.subscribeOn(Schedulers.io())
.doOnNext(number -> processExecution())
.observeOn(Schedulers.from(command -> tasks.add(command)))
.subscribe(x -> System.out.println("Thread:" + Thread.currentThread().getName() + " value:" + x));
tasks.take().run();
}
private void processExecution() {
System.out.println("Execution in " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
关于您的问题不会在RxJava2中出现。建议使用RxJava2。 我比较了RxJava-1.2.7和RxJava-2.0.7,找到了根本原因。现在我正在寻找解决办法
在RxJava-1.2.7.中,您可以看到
observeObserveon#145
,并在调用请求时找到它计划
任务。这意味着当您订阅时,它将调用Executor.execute
。因此,您的任务队列立即接受Runnable
。然后您获取并运行Runnable
(这是实际的ExecutorSchedulerWorker
),但是上游的onNext
没有被调用(因为您睡眠时间为2000ms)。它将在ObserveOnSubscriber#213
上返回null
。当上游调用onNext(Integer)
时,任务将永远不会运行。您的问题不会在RxJava2中出现。建议使用RxJava2。
我比较了RxJava-1.2.7和RxJava-2.0.7,找到了根本原因。现在我正在寻找解决办法
在RxJava-1.2.7.中,您可以看到
observeObserveon#145
,并在调用请求时找到它计划
任务。这意味着当您订阅时,它将调用Executor.execute
。因此,您的任务队列立即接受Runnable
。然后您获取并运行Runnable
(这是实际的ExecutorSchedulerWorker
),但是上游的onNext
没有被调用(因为您睡眠时间为2000ms)。它将在ObserveOnSubscriber#213
上返回null
。当上游调用onNext(Integer)
时,该任务将永远不会运行。这种方法的问题是,您不知道在给定的时间应该执行多少任务,也不知道在取消阻止主线程后应该等待的任务是否会死锁
我知道,1.x的任何扩展都不支持返回Java主线程。对于2.x,extensions项目中提供了以下功能:
public static void main(String[] args) {
BlockingScheduler scheduler = new BlockingScheduler();
scheduler.execute(() -> {
Flowable.range(1,10)
.subscribeOn(Schedulers.io())
.observeOn(scheduler)
.doAfterTerminate(() -> scheduler.shutdown())
.subscribe(v -> System.out.println(v + " on " + Thread.currentThread()));
});
System.out.println("BlockingScheduler finished");
}
请注意调用
scheduler.shutdown()
,最终必须调用它才能释放主线程,否则,您的程序可能永远不会终止。您的方法的问题是,您不知道在给定时间应该执行多少任务,也不知道在取消阻止主线程后应该等待的任务是否死锁
我知道,1.x的任何扩展都不支持返回Java主线程。对于2.x,extensions项目中提供了以下功能:
public static void main(String[] args) {
BlockingScheduler scheduler = new BlockingScheduler();
scheduler.execute(() -> {
Flowable.range(1,10)
.subscribeOn(Schedulers.io())
.observeOn(scheduler)
.doAfterTerminate(() -> scheduler.shutdown())
.subscribe(v -> System.out.println(v + " on " + Thread.currentThread()));
});
System.out.println("BlockingScheduler finished");
}
请注意调用调度程序.shutdown(),最终必须调用该调用才能释放主线程,否则程序可能永远不会终止。我只是根据akanord的建议更新代码,但这一做法似乎会阻止一个任务到另一个任务,并最终按顺序运行 使用代码:
@Test
public void testBackToMainThread() throws InterruptedException {
processValue(1);
processValue(2);
processValue(3);
processValue(4);
processValue(5);
System.out.println("done");
}
private void processValue(int value) throws InterruptedException {
BlockingScheduler scheduler = new BlockingScheduler();
scheduler.execute(() -> Flowable.just(value)
.subscribeOn(Schedulers.io())
.doOnNext(number -> processExecution())
.observeOn(scheduler)
.doAfterTerminate(() -> scheduler.shutdown())
.subscribe(v -> System.out.println(v + " on " + Thread.currentThread())));
}
private void processExecution() {
System.out.println("Execution in " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
以及输出
Execution in RxCachedThreadScheduler-1
1 on Thread[main,5,main]
Execution in RxCachedThreadScheduler-1
2 on Thread[main,5,main]
Execution in RxCachedThreadScheduler-1
3 on Thread[main,5,main]
Execution in RxCachedThreadScheduler-1
4 on Thread[main,5,main]
Execution in RxCachedThreadScheduler-1
5 on Thread[main,5,main]
done
我想要实现的是这个输出
Execution in RxCachedThreadScheduler-1
Execution in RxCachedThreadScheduler-1
Execution in RxCachedThreadScheduler-1
Execution in RxCachedThreadScheduler-1
Execution in RxCachedThreadScheduler-1
1 on Thread[main,5,main]
2 on Thread[main,5,main]
3 on Thread[main,5,main]
4 on Thread[main,5,main]
5 on Thread[main,5,main]
done
因此,每次主线程运行管道时,在另一个线程中运行onNext,然后它从方法返回,直到另一个线程完成并使其成为主线程返回管道。我只是根据akanord的建议更新代码,但这一做法似乎会阻止一个任务到另一个任务,然后按顺序运行 使用代码:
@Test
public void testBackToMainThread() throws InterruptedException {
processValue(1);
processValue(2);
processValue(3);
processValue(4);
processValue(5);
System.out.println("done");
}
private void processValue(int value) throws InterruptedException {
BlockingScheduler scheduler = new BlockingScheduler();
scheduler.execute(() -> Flowable.just(value)
.subscribeOn(Schedulers.io())
.doOnNext(number -> processExecution())
.observeOn(scheduler)
.doAfterTerminate(() -> scheduler.shutdown())
.subscribe(v -> System.out.println(v + " on " + Thread.currentThread())));
}
private void processExecution() {
System.out.println("Execution in " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
以及输出
Execution in RxCachedThreadScheduler-1
1 on Thread[main,5,main]
Execution in RxCachedThreadScheduler-1
2 on Thread[main,5,main]
Execution in RxCachedThreadScheduler-1
3 on Thread[main,5,main]
Execution in RxCachedThreadScheduler-1
4 on Thread[main,5,main]
Execution in RxCachedThreadScheduler-1
5 on Thread[main,5,main]
done
我想要实现的是这个输出
Execution in RxCachedThreadScheduler-1
Execution in RxCachedThreadScheduler-1
Execution in RxCachedThreadScheduler-1
Execution in RxCachedThreadScheduler-1
Execution in RxCachedThreadScheduler-1
1 on Thread[main,5,main]
2 on Thread[main,5,main]
3 on Thread[main,5,main]
4 on Thread[main,5,main]
5 on Thread[main,5,main]
done
因此,每次主线程运行管道时,在另一个线程中运行onNext,然后它从方法返回,直到另一个线程完成并使其成为主线程返回管道。我运行您的代码,并按预期输出。你的问题是什么?打印线程:永远不会发生只有执行:然后doneSorry,我不明白你的意思。你看到这个控制台打印吗??println(“线程:“+Thread.currentThread().getName()+”值:“+x”)它将打印
main
,因为您总是在主线程中执行并运行任务。我按预期运行您的代码并输出。你的问题是什么?打印线程:永远不会发生只有执行:然后doneSorry,我不明白你的意思。你看到这个控制台打印吗??println(“线程:+Thread.currentThread().getName()+”值:“+x”)它将打印main
,因为您总是在主线程中执行任务。我认为标题的格式不正确。对不起,我还是不明白你的意思。你能详细说明一个例子吗?谢谢@保罗,我可以给你一个快速的解决方案。重复任务。take().run()
两次,然后您将看到所需的输出。我认为标题格式不正确。对不起,我还是不明白你的意思。你能详细说明一个例子吗?谢谢@保罗,我可以给你一个快速的解决方案。重复tasks.take().run()
两次,然后您将看到所需的输出。我尝试了您的aproach,但它似乎是按顺序运行的。你能看一下我的第二篇文章吗?我试过你的方法,但它似乎是按顺序运行的。你能看一下我的第二篇文章吗?你必须用blocking scheduler包含所有任务,而不是为每个项目单独创建一个blocking scheduler。如果我将BlockingScheduler定义为全局范围,那么它只执行第一个任务。在线程[main,5,main]上的RxCachedThreadScheduler-11中执行完毕我开始认为我想要的东西根本没有任何意义。无论如何,主线程都必须等待将来的某个时刻。您必须使用blocking scheduler包含所有任务,而不是为每个项目单独创建blocking scheduler。如果我将BlockingScheduler定义为全局作用域,则仅执行它的第一个任务。在线程[main]上的RxCachedThreadScheduler-1中执行