java - 是什么让异步单线程 java 代码异步
问题描述
所以我们目前正在用java开发一个应用程序,一位同事向我介绍了异步编程,不管我研究了多少,对我来说似乎是同步的。因此,异步代码的主要优点似乎是 UI 不会冻结,而某些操作需要很长时间才能执行并返回结果,我们需要做的就是给该函数一个回调函数,该函数将被调用当工作完成时。根据我从在线资源和stackoverflow上的类似问题了解到,代码可以是单线程和异步的,甚至有人这样画:
异步(一个线程)(信用:异步与同步执行,它的真正含义是什么?):
A-Start ------------------------------------------ A-End
| B-Start -----------------------------------------|--- B-End
| | C-Start ------------------- C-End | |
| | | | | |
V V V V V V
1 thread->|<-A-|<--B---|<-C-|-A-|-C-|--A--|-B-|--C-->|---A---->|--B-->|
所以据我了解,单线程异步代码仍然是同步的,但它给每个任务一点时间,如果有很多事情要做,异步代码基本上说在工作完成后给我回电话,好的,但如果我们只有当您将资源提供给其他代码时,一个线程将完成这项工作?
为了向您展示问题,让我们看一下我们项目中的示例:
public void getAllExercises(RequestListener<List<Exercise>> listener) {
getAllExercisesRequest().getAsObjectList(Exercise.class, listener);
}
该方法的用法:当用户单击按钮查看所有练习时,将调用此方法,它的作用是从服务器获取所有练习,这是一个用法示例:
class sometingAdapter extends something{
someMethod(param){
.
.
.
//some code before the Method call
DBClient.getstandardDBClient().getAllExercises(new RequestListener<List<Exercise>>() {
@Override
public void onResponse(List<Exercise> response) {
arrayAdapter.addAll(response);
arrayAdapter.notifyDataSetChanged();
}
});
//some additional code
return v;
}-> end of the method
}
声称现在当方法从服务器获取数据时,我们的 UI 没有被阻塞,并且可以执行其他操作,但是如何执行呢?当代码执行到该行时DBClient.getStandardDBClient().getAllExercises
,该方法getAllExercises
被调用,执行跳转到该方法。在该方法内部构建了一个请求并getAsObject(MyClass.class, listener)
调用了方法(我不知道方法是如何getAsObject()
工作的,它来自 FAN API),
但是我们或系统在哪里告诉代码,听你可以回去做你的事情,当我有数据(响应)时,我会用你作为参数传递的onResponse()
方法给你回电listener
谁负责获取数据我们只有一个线程,没有神奇的资源可以在我们的线程忙于执行其他代码时获取数据?当其他代码正在运行时,系统如何知道在哪里跳回?它不像系统就像“哦,他正在异步执行,我会神奇地跳来跳去”
所以在这个魔法发生之后,还有一件事情让我感到困惑,而当代码的进一步执行到达return v
语句时,对 getAllExercises 的调用仍然处于活动状态,不是这样,函数调用就会从堆栈中删除,这将进一步意味着getAllExercise 方法的执行会被中断吗?这进一步意味着提取也会被中断等。基本上它会导致连锁反应,并且永远不会调用 onResponse() 方法,还是会这样?
是什么使代码异步,它是否只传递一个回调方法,即其方法用作回调的对象?如果是这样,那如何不阻塞 UI,如果我调用一个方法并将该方法传递给另一个方法,那么代码的执行将在该方法内部,直到调用传递的方法,然后执行该代码将开始,所以仍然有 UI 阻塞没有神奇的跳跃和在后台工作,我错过了什么?
void Method1(Method2);
|Start
|call Method1------------>|
| |
| Blocked?? |Execution of Method 1
| |
| <-----------------------|
| callback Method2
| continued execution
|
|
|End
那么,在被阻塞的部分变得畅通的地方,魔法发生在哪里呢?并且method1和其余部分的执行同时发生?
我的理解是,以某种方式发生以下情况:
void Method1(Method2);
|Start
|call Method1------------------>|
continues execution of main thread|<------------------------------|
|(okay thanks for the Method |Execution of Method 1
|I will call you when I am done)|but what resource is executing
| <---------------------------- |Method 1????
| callback Method2: Iam done
| ------------------------------>|execution of method 2
| Blocked |very quick not noticable
|<-------------------------------
|continued execution
|End
解决方案
通常在 Java 中,如果你不想让你的 UI 阻塞,你将不得不在另一个线程上运行复杂的任务。在不知道这个“FAN API”的情况下,我几乎可以肯定地说,那getAsObjectList(...)
是开始第二个线程。
此方法将在没有明显延迟的情况下返回,并允许当前线程继续进行,即防止 UI 阻塞。它不是同步启动请求,而是启动一个新线程(或者更确切地说从线程池中获取一个线程)并使用它来发送和等待请求。当收到响应时,它会RequestListener
从这个线程(或者可能是另一个线程)调用你。也就是说,它不会使用调用getAsObjectList(...)
来运行的RequestListener
线程,因为该线程已经从getAsObjectList(...)
很久以前返回并且不再被“控制”。¹特别是不会有一些“魔术”随意中断线程在继续执行的任何随机点,并强制将执行填充RequestListener
到其控制流中。
¹:如果getAllExercises(...)
从某个线程调用,该线程是线程池/基于事件队列的并发框架的一部分(可能是 UI 框架的一部分),则实际上有可能,该线程将有意(或什至只是偶然)成为重用调用RequestListener
. 例如,请参见JavaScript 的并发模型,其中所有(客户端)代码仅在单个线程中运行,同时仍允许/鼓励/强制执行异步性。getAsObjectList(...)
但是,在您的调用周围的客户端代码顺利执行之前,这仍然不会发生。只有在执行完成后,线程在其池中返回到某个静止状态,等待更多任务运行,它才能被选为现在调用RequestListener
on 的线程。
推荐阅读
- css - Is there a way to 'peg' the size of a font to the size of the browser window (with and height and line height, padding etc)?
- azure-eventhub - Azure Event Hub - Process data through scala script
- php - 如何以编程方式获取已安装的作曲家包?
- javascript - Javascript将数组推入另一个数组
- windows-update - How to prevent Windows from automatically restarting due to security updates installation
- c# - Why use bitwise instead of logical operators on nullable boolean types?
- git - Is there a way to 'bump the version' without version commits?
- php - How to call a return value from a function into another function that has already a parameter?
- javascript - sinon stub 在 ESM 项目中的最佳实践
- graphics - 重新编写和使用 ReProcessing