Servlet3中的AsyncContext异步和多线程异步有什么区别

Servlet3中的AsyncContext异步和多线程异步有什么区别,第1张

异步和多线程可以说没有必然的联系,只能说异步可以通过多线程实现而已
要理解这些东西,你得具备很多相关的知识, *** 作系统原理,编译原理等
简单地来说,计算机或者说CPU执行你的代码都是顺序执行的,当前的语句没有执行完,不会执行后面的语句的,这是永远不变的规则!
但是这样的机制会使整个执行效率很低,因为CPU总是要等待当前的语句执行完毕了才会执行后面的代码,而计算机在绝多数的时候都是处于等待用户的输入,等待磁盘文件的读取完成,等待网络数据的传输完成中,所以为了提高整个系统的运行效率,提高CPU的执行效率,计算机系统引入了异步的机制。
异步机制,简单地说就是CPU不会傻傻地处于等待状态,它会先干别的事情,当它需要的东西已经准备完毕后(大多数的情况都是等待外部的输入数据准备完毕,也有些是复杂的计算完毕),硬件系统给CPU一个中断,告诉有了新的数据了,你现在可以去处理了。
这就是最基本的异步原理,而现代 *** 作 *** 作系统对硬件系统做了良好的封装,把很多底层机制屏蔽了,为程序的开发者提供了事件和多线程的概念,让程序的开发者可以更好地利用异步机制。
再说说多线程吧。多线程是计算机引入了 *** 作系统之后才有的概念,至于为什么计算机要引入 *** 作系统,在此就不叙述了,自行了解。多线程的实现有两个方法,一个就是增加CPU的核数和个数,这是最直接的方法,还有一种是采用CPU轮询的方式,每个进程都执行一段时间,又去执行另一个进程的指令,由于切换的速度非常的快,给人的感觉就是同时执行的。
说了这么多,你可能很失望,因为没有代码,没有举例。但我想说的是,用代码无法说明这个问题,不同的 *** 作系统,不同的编程语言,不同的编程框架,对异步和多线程的定义和处理是不一样的,但原理就是这样的。
我们写代码无非就是写一堆的指令去要求CPU执行,同步的方式就是这样的:
我:hi,CPU,我要你做一件事情,而且必须立刻马上就做,因为我正在等着你。
CPU:那你就等着吧,我现在去做。
异步的方式是这样的:
我:hi,CPU,我要你做一件事情,但是不是立刻就做,你可以交给下面的人去做,或者找一个帮手来,我们继续做后面的事情
CPU:好的,我现在通知硬件去做,等有结果了我通过事件告诉你
或者
CPU:好的,我让另一个核心来做这件事情,我们继续(其实多线程是 *** 作系统实现的,我只是这么举个例子而已)

大家都知道,java是同步顺序执行。当需要异步执行时,需要新创建一个线程完成。
1 使用常规的方法显示异步调用

第一步 新建 ThreadTestjava 实现 Runnable 接口

第二步 新建测试执行

当然,除了这种显式 new Thread 对象,我们通过线程池获取线程名称,这里不做演示。我们熟悉的spring 在 spring3中提供了@Async注解,来方便开发者优雅的使用异步调用。
2使用 springboot @Async注解,优雅的实现异步调用

第一步 开启 异步调用注解。

第二步 定义线程池

第三步 创建service 测试类 TestServicejava

第四步 新建 Service 实现类 ,TestServiceImpljava

第五步 测试执行 ,执行结果

SpringBoot使用@Async优雅的异步调用就暂时记录到这里,欢迎评论区一起讨论学习。

下面给你介绍4种线程池:

1、newCachedThreadPool:

底层:返回ThreadPoolExecutor实例,corePoolSize为0;maximumPoolSize为IntegerMAX_VALUE;keepAliveTime为60L;unit为TimeUnitSECONDS;workQueue为SynchronousQueue(同步队列)

通俗:当有新任务到来,则插入到SynchronousQueue中,由于SynchronousQueue是同步队列,因此会在池中寻找可用线程来执行,若有可以线程则执行,若没有可用线程则创建一个线程来执行该任务;若池中线程空闲时间超过指定大小,则该线程会被销毁。

适用:执行很多短期异步的小程序或者负载较轻的服务器

2、newFixedThreadPool:


底层:返回ThreadPoolExecutor实例,接收参数为所设定线程数量nThread,corePoolSize为nThread,maximumPoolSize为nThread;keepAliveTime为0L(不限时);unit为:TimeUnitMILLISECONDS;WorkQueue为:new LinkedBlockingQueue<Runnable>() 无解阻塞队列

通俗:创建可容纳固定数量线程的池子,每隔线程的存活时间是无限的,当池子满了就不在添加线程了;如果池中的所有线程均在繁忙状态,对于新任务会进入阻塞队列中(无界的阻塞队列)

适用:执行长期的任务,性能好很多

3、newSingleThreadExecutor

底层:FinalizableDelegatedExecutorService包装的ThreadPoolExecutor实例,corePoolSize为1;maximumPoolSize为1;keepAliveTime为0L;unit为:TimeUnitMILLISECONDS;workQueue为:new LinkedBlockingQueue<Runnable>() 无解阻塞队列

通俗:创建只有一个线程的线程池,且线程的存活时间是无限的;当该线程正繁忙时,对于新任务会进入阻塞队列中(无界的阻塞队列)

适用:一个任务一个任务执行的场景

4、NewScheduledThreadPool:

底层:创建ScheduledThreadPoolExecutor实例,corePoolSize为传递来的参数,maximumPoolSize为IntegerMAX_VALUE;keepAliveTime为0;unit为:TimeUnitNANOSECONDS;workQueue为:new DelayedWorkQueue() 一个按超时时间升序排序的队列

通俗:创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构

适用:周期性执行任务的场景

最后给你说一下线程池任务执行流程:

当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。

当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行

当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务

当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理

当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程

当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

1、关于异步:java中异步请求就是调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理

两个相减就是运行时间。启动线程之前,获取系统时间,做为开始时间,线程结束后,在线程最后再获取一次系统时间,这个时间减去刚刚上面的那个时间,就是运算时间,记录一个起始时间,记录一个结束时间,两个相减就是程序运行时间。

简介:
BIO:同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
NIO:同步非阻塞式IO,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
AIO(NIO2):异步非阻塞式IO,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
各自应用场景:
(1)NIO适合处理连接数目特别多,但是连接比较短(轻 *** 作)的场景,Jetty,Mina,ZooKeeper等都是基于java nio实现。
(2)BIO方式适用于连接数目比较小且固定的场景,这种方式对服务器资源要求比较高,并发局限于应用中。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/12982500.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2025-08-29
下一篇2025-08-29

发表评论

登录后才能评论

评论列表(0条)

    保存