一、怎么理解异步和同步
- 从方法的角度去理解:
- 需要等待结果返回,才能继续运行就是
同步
- 不需要等待结果返回,就能继续运行就是
异步
- 需要等待结果返回,才能继续运行就是
- 注意:同步在多线程中还有另外一层意思:
是让多个线程步调一致
。
同步调用
- 同步调用意味着在调用一个函数或方法时,调用者会等待该函数或方法执行完成并返回结果后,才会继续执行后续的代码。在多线程环境中,如果线程A调用了一个同步方法,那么线程A会在该方法执行完成之前被阻塞,无法继续执行其他任务。
- 同步调用的特点是:
- 调用者会等待被调用者执行完成。
- 保证了任务执行的顺序性和结果的确定性。
- 但可能会导致线程阻塞,降低系统的并发性能。
异步调用
-
异步调用则不同,当调用一个异步函数或方法时,调用者不会等待该函数或方法执行完成,而是立即返回并继续执行后续的代码。被调用的函数或方法会在后台线程中执行,当执行完成后,通常会通过回调函数、Future/Promise对象或其他机制来通知调用者。
-
异步调用的特点是:
- 调用者不会等待被调用者执行完成。
- 提高了系统的并发性能,因为调用者可以继续执行其他任务。
- 但需要处理异步结果,增加了代码的复杂性。
多线程的应用——异步调用(案例1)
-
单个线程的时候,所有代码都在同一个线程执行(下面的就是在main线程中执行),代码执行的时候都是同步的(即后面代码的执行需要等前面代码执行完成才可以继续执行)
-
多线程可以让方法执行变为异步的(即不用等待前面代码的执行)比如说这里的读取磁盘文件时,假设读取操作花费了 5 秒钟,如果没有线程调度机制,这 5 秒 cpu 什么都做不了,其它代码都得暂停…(如上图)
-
使用多线程之后,读取文件的操作放在一个新的线程中执行,那么后面的代码就不需要等待读取文件操作完成之后再执行了,因为后面的代码与文件读取操作的代码不在同一个线程中,这就可以理解为多线程的异步调用
三、多线程异步调用的场景
- 比如在项目中,视频文件需要转换格式等操作比较费时,这时开一个新线程来处理视频转换,这样就可以避免阻塞主线程。
- tomcat 的异步 servlet 也是类似的目的,它让用户线程处理耗时较长的操作,这样可以避免阻塞 tomcat 的工作线程
- 在ui 程序中,可以开新线程进行其他操作,这样可以避免阻塞 ui 线程
- 。。。。。。。
四、多线程异步调用和多线程同步调用的概念理解
- 多线程的异步调用和同步调用是并发编程中的核心概念,它们决定了线程之间如何协作以及任务如何被执行。
一、多线程的同步调用
- 定义:多线程的同步调用指的是多个线程在访问共享资源时,需要按照某种顺序来确保资源在某一时刻只能被一个线程使用,以避免数据竞争和不一致的问题。
- 特点:
- 线程之间需要相互等待和协调,以确保资源的正确访问。
- 同步机制(如锁、信号量等)被用来控制对共享资源的访问。
- 提高了数据的一致性和安全性,但可能导致线程阻塞和性能下降。
- 实现方式:
- 使用synchronized关键字:在Java中,可以通过在方法或代码块上使用synchronized关键字来实现同步。
- 使用锁(Lock):除了synchronized,还可以使用Java提供的ReentrantLock等锁机制来实现更灵活的同步控制。
- 使用信号量(Semaphore):信号量是一种更高级的同步机制,可以控制同时访问共享资源的线程数量。
- 适用场景:
- 当多个线程需要访问和操作共享数据时,使用同步调用可以确保数据的一致性和安全性。
- 在需要保护临界区或实现互斥访问的场景中,同步调用也是必要的。
二、多线程的异步调用
- 定义:多线程的异步调用指的是线程之间不需要相互等待,一个线程可以在不阻塞其他线程的情况下继续执行其他任务。异步调用通常通过回调函数、Future/Promise对象或其他机制来通知调用者任务的结果。
- 特点:
- 线程之间不需要相互等待,提高了系统的并发性和响应速度。
- 异步调用不会阻塞调用线程,使得调用线程可以继续执行其他任务。
- 增加了代码的复杂性和调试难度,因为需要处理异步结果和可能的错误。
- 实现方式:
- 使用线程池:线程池可以管理一组线程,并允许开发者以异步方式提交任务给这些线程执行。
- 使用回调函数:当异步任务完成时,可以通过回调函数来处理任务的结果。
- 使用Future/Promise对象:这些对象提供了获取异步任务结果的方法,并允许在任务完成时设置结果或异常。
- 适用场景:
- 当任务需要执行耗时的I/O操作时(如网络请求、文件读写等),使用异步调用可以提高系统的响应速度和并发性能。
- 在需要执行多个独立任务并希望并行处理它们的场景中,异步调用也是有效的选择。
三、比较与选择
- 性能:
- 同步调用在保护共享资源和确保数据一致性方面表现更好,但可能导致线程阻塞和性能下降。
- 异步调用提高了系统的并发性和响应速度,但增加了代码的复杂性和调试难度。
- 适用场景:
- 同步调用适用于需要保护共享资源和确保数据一致性的场景。
- 异步调用适用于需要执行耗时I/O操作或并行处理多个独立任务的场景。
- 选择建议:
- 在选择同步或异步调用时,需要根据具体的应用场景和需求进行权衡。
- 如果数据一致性和安全性是首要考虑因素,那么同步调用可能是更好的选择。
- 如果系统的并发性能和响应速度是首要考虑因素,并且可以接受一定的代码复杂性和调试难度,那么异步调用可能是更合适的选择。
多线程的应用——提高效率(案例2)
- 单核 cpu 下,多线程不能实际提高程序运行效率,只是为了能够在不同的任务之间切换,不同线程轮流使用cpu ,不至于一个线程总占用 cpu,别的线程没法干活
- 多核 cpu 可以并行跑多个线程,但能否提高程序运行效率还是要分情况的,有些任务,经过精心设计,将任务拆分,并行执行,当然可以提高程序的运行效率。但不是所有计算任务都能拆分的,也不是所有任务都需要拆分,任务的目的如果不同,谈拆分和效率没啥意义
- IO 操作不占用 cpu,只是我们一般拷贝文件使用的是【阻塞 IO】,这时相当于线程虽然不用 cpu,但需要一直等待 IO 结束,没能充分利用线程。所以才有后面的【非阻塞 IO】和【异步 IO】优化。