zoukankan      html  css  js  c++  java
  • 为什么 asnyc await 可以提高web程序的吞吐量

    (转网上一段话)

    Web程序天生就是多线程的,且web线程都是跑的线程池线程(使用线程池线程是为了避免不断创建、销毁线程所造成的资源成本浪费),而线程池线程可使用线程数量是一定的,尽管可以设置,但它还是会在一定范围内。如此一来,我们web线程是珍贵的(物以稀为贵),不能滥用。用完了,那么其他用户请求的时候就无法处理直接503了。

    那什么算是滥用呢?比如:文件读取、URL请求、数据库访问等IO请求。如果用web线程来做这个耗时的IO操作那么就会阻塞web线程,而web线程阻塞得多了web线程池线程就不够用了。也就达到了web程序最大访问数。

    此时我们的新异步 async await 横空出世,解放了那些原本处理IO请求而阻塞的web线程(想偷懒?没门,干活了。)。通过异步方式使用相对廉价的线程(非web线程池线程)来处理IO操作,这样web线程池线程就可以解放出来处理更多的请求了。

    测试代码:

        public class TestAsyncController : ApiController
        {
            public async void Test(string id)
            {
                try
                {
                    Trace.WriteLine("before the await,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                    await GetData(id);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex);
                }
                Trace.WriteLine("after the await,the thread id id " + Thread.CurrentThread.ManagedThreadId);
                Trace.WriteLine("");
            }
    
    
            public Task GetData(string id)
            {
                if (id == null)
                {
                    throw new Exception("抛个异常试试!");
                }
                Trace.WriteLine("before task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                var tk = Task.Run(() =>
                {
                    Trace.WriteLine("in the task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                    Trace.WriteLine("sleep 3 秒");
                    Thread.Sleep(3000);
                    Trace.WriteLine("sleep end");
                });
                Trace.WriteLine("after task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                return tk;
            }
        }

    可以看出来, before the await 和 after the await 后的线程ID不一样,说明执行到GetData()方面里面的Task时,web线程就被解放出来了.

    如果去掉async 和 await ,在GetData() 方法里面加上 Task.WaitAll(tk) 结果会是什么呢?

            public void Test(string id)
            {
                try
                {
                    Trace.WriteLine("before the await,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                    GetData(id);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(ex);
                }
                Trace.WriteLine("after the await,the thread id id " + Thread.CurrentThread.ManagedThreadId);
                Trace.WriteLine("");
            }
    
    
            public Task GetData(string id)
            {
                if (id == null)
                {
                    throw new Exception("抛个异常试试!");
                }
                Trace.WriteLine("before task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                var tk = Task.Run(() =>
                {
                    Trace.WriteLine("in the task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                    Trace.WriteLine("sleep 3 秒");
                    Thread.Sleep(3000);
                    Trace.WriteLine("sleep end");
                });
                Task.WaitAll(tk);
                Trace.WriteLine("after task.run,the thread id is " + Thread.CurrentThread.ManagedThreadId);
                return tk;
            }

    结果如下:

    before the await 和 after the await 的线程ID 永远一样.说明web线程是一样的

  • 相关阅读:
    快速上手php:使用PhpStrom调试php
    快速上手php:使用PhpStrom部署项目
    使用自定义tld标签简化jsp的繁琐操作
    京东购物体验杂谈
    Mysql将近两个月的记录合并为一行显示
    学习WebSocket(二):使用Spring WebSocket做一个简单聊天室
    学习WebSocket(一):Spring WebSocket的简单使用
    springMVC的@ResponseBody、@RequestBody使用需要注意的地方
    如何使用maven建一个web3.0的项目
    项目管理工具 Redmine 安装试用手记
  • 原文地址:https://www.cnblogs.com/refuge/p/8502787.html
Copyright © 2011-2022 走看看