什么使异步单线程java代码异步

yfwxisqw  于 2021-07-07  发布在  Java
关注(0)|答案(1)|浏览(295)

因此,我们目前正在用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 你作为论点通过的
谁负责获取数据我们只有一个线程,没有神奇的资源在线程忙于执行其他代码时获取数据?当其他代码正在运行时,系统如何知道在何处跳回?它不像系统是“哦,他在异步做,我会神奇地跳来跳去”
因此,在这个神奇的事情发生之后,还有一件事让我困惑,当代码的进一步执行到达目标时,对getallexercises的调用仍然是活动的 return v 是不是这样函数调用就从堆栈中删除了,这就意味着getallexercise方法的执行将被中断?这进一步意味着获取也会被中断等等,基本上它会引起连锁React,onresponse()方法永远不会被调用,或者它会被调用吗?
是什么使代码异步,它只是传递一个回调方法,即对象的方法被用作回调?如果是这样,那怎么不阻塞ui呢?如果我调用一个方法并将这个方法传递给另一个方法,那么代码的执行将在方法内部,直到调用传递的方法,那么代码的执行将开始,所以ui仍然被阻塞没有神奇的跳跃和在后台工作,我错过了什么?

void Method1(Method2);

                                    |Start 
                                    |call Method1------------>|
                                    |                         |                         
                                    | Blocked??               |Execution of Method 1
                                    |                         |
                                    | <-----------------------|
                                    |    callback Method2
                                    | continued execution 
                                    | 
                                    |
                                    |End

那么,当被阻塞的部分被解除阻塞时,魔法会发生在哪里呢?方法1和其他方法的执行是同时进行的?
我的理解是这样的:

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
tzdcorbm

tzdcorbm1#

一般来说,在java中,如果不想阻塞ui,就必须在另一个线程上运行复杂的任务。如果不知道这个“fanapi”,我几乎可以肯定地说 getAsObjectList(...) 正在启动第二个线程。
这个方法将返回而没有明显的延迟,并允许当前线程继续,即。e。防止ui阻塞。它不是同步启动请求,而是启动一个新线程(或者从线程池中获取一个线程),并使用它来发送和等待请求。当收到回复时,它将呼叫您的 RequestListener 从这个线程(或者可能是另一个线程)。也就是说,它不会使用线程,即调用 getAsObjectList(...) 运行 RequestListener ,因为该线程已从 getAsObjectList(...) 很久以前了,再也不能被“控制”了。¹ 特别是,不会有一些“魔法”在任意点自由地中断线程的继续执行,并强行填充线程的执行 RequestListener 进入它的控制流。
¹: 如果 getAllExercises(...) 是从某个线程调用的,即线程池/某个基于事件队列的并发框架的一部分(可能是ui框架的一部分),事实上,有可能有意(甚至只是无意)重用此线程来调用 RequestListener . 例如,请参阅javascript的并发模型,其中所有(客户机)代码仅在单个线程中运行,同时仍然允许/鼓励/强制执行异步性。但是,在您的客户机代码调用 getAsObjectList(...) 执行顺利。只有在执行完成,线程返回到其池中的某个静止状态,等待更多的任务运行之后,才可以选择它作为现在调用 RequestListener 打开。

相关问题