我正在探索使用Spring Boot的异步servlet。据我所知,异步servlet用于在一个线程中执行长时间运行的任务,而不是容器为处理请求而启动的线程,这样容器就可以使用自己的线程来处理其他连接。基于这样的理解,我尝试了以下代码:
@WebServlet(asyncSupported = true, urlPatterns = "/demo")
@Component
public class demo extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final AsyncContext context = request.startAsync();
ServletOutputStream stream = response.getOutputStream();
WriteListener listener = new WriteListener() {
@Override
public void onWritePossible() throws IOException {
System.out.println(Thread.currentThread().getId());
ServletOutputStream output = context.getResponse().getOutputStream();
if (output.isReady()) {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
output.print("Heloooooooooo");
}
context.complete();
}
@Override
public void onError(Throwable throwable) {
throwable.printStackTrace(System.err);
context.complete();
}
};
stream.setWriteListener(listener);
System.out.println(Thread.currentThread().getId());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
// TODO Auto-generated method stub
}
}
但问题是,运行doGet
的同一线程正在调用OnWriteProbabile
方法。不是应该不一样吗?
在doGet
方法中,您已经创建了一个AsyncContext
,您有责任将它进一步传递给一个不同的线程,该线程将通过设置result-servlet容器不会为您创建一个新线程来完成处理(稍后)。
在asynccontext
传递给不同的线程之后,doget
可以立即返回,从而释放servlet容器的执行器线程来服务新的请求。
基于您的代码的示例:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
final AsyncContext context = request.startAsync();
System.out.println("Servlet container thread before async started: "
+ Thread.currentThread().getName());
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("New thread started: "
+ Thread.currentThread().getName());
ServletOutputStream output = context.getResponse().getOutputStream();
TimeUnit.SECONDS.sleep(3);
System.out.println("New thread writing response: "
+ Thread.currentThread().getName());
output.print("Hi!");
context.complete();
} catch (Throwable e) {
e.printStackTrace();
}
}
}).start();
System.out.println("Servlet container thread returning: "
+ Thread.currentThread().getName());
}
Servlet container thread before async started: http-nio-8080-exec-1
Servlet container thread returning: http-nio-8080-exec-1
New thread started: Thread-3
New thread writing response: Thread-3
如果您使用Spring Boot,您可以实现一个控制器
,它返回一个可调用
,Spring Framework将确保可调用
是在一个生命周期由Spring管理的不同线程中执行的。
如果您想在没有Spring的情况下执行此操作(这也很好),通常可以通过将AsyncContext
放在队列中,并让一个ExecutorService
使用排队的请求来完成此操作。
当我调用foo()时,这个方法是否在单独的线程上运行?
这是在一次Android采访中被问到的。有人问我是否可以从异步任务 1 的 doInBackground() 方法(让它成为 Task1)启动另一个异步任务(让它成为 Task2)。我浏览了文档,其中说了以下内容: 必须在UI线程上创建任务实例。 必须在 UI 线程上调用 execute(Params...)。 根据这些陈述,我认为从另一个任务的后台方法启动一个任务是不可能的。此外,async任务
在Server程序中如果需要执行很耗时的操作,比如一个聊天服务器发送广播,Web服务器中发送邮件。如果直接去执行这些函数就会阻塞当前进程,导致服务器响应变慢。 Swoole提供了异步任务处理的功能,可以投递一个异步任务到TaskWorker进程池中执行,不影响当前请求的处理速度。 程序代码 基于第一个TCP服务器,只需要增加onTask和onFinish 2个事件回调函数即可。另外需要设置task
本文向大家介绍C#异步执行任务的方法,包括了C#异步执行任务的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#异步执行任务的方法。分享给大家供大家参考。具体如下: 希望本文所述对大家的C#程序设计有所帮助。
问题内容: 我正在Flask中编写一个应用程序,除了同步和阻塞之外,它的运行情况非常好。我特别有一项任务,该任务调出第三方API,该任务可能需要几分钟才能完成。我想拨打该电话(实际上是一系列电话)并使其运行。同时控制权返回给Flask。 我的看法如下: 现在,我要做的就是 运行并提供在方法返回时要执行的回调,而Flask可以继续处理请求。这是我需要Flask异步运行的唯一任务,并且我想就如何最好地
我在StackOverflow的职业生涯中有一个第一个问题。我希望是你帮我。 发生了什么: