zoukankan      html  css  js  c++  java
  • 异步与线程阻塞

    返回目录

    应该这样理解它

    异步,早期开发人员对它有很多误解,认为不阻塞主线程就是异步,更有认为不阻塞UI就是异步,但异步归根结底和这两个东西关系并不大,异步的出现主要是为了提高线程的利用率,让可用线程更高,而不是一个线程只做一件事,这件事没有完成就不去做下面的事情,这是不正确的,线程应该被解放出来!事实上,你如果学过nodejs的话,对单线程非阻塞应该更清楚一些,它主要通过方法回调来实现异步的,只是在语法上和C#不太一样。

    说一下上面提到的误解

    误解1:不阻塞主线程

    如果不阻塞主线程的话,你只能开个新线程完成这个动作,像一些系统通知,它和主线程的工作流程没有关系,如果开个新线程,与主线程并行执行,这并不是我们说的异步,这只是多线程!它会增加线程的开支,使用不当,会影响系统的吞吐量!

    误解2:不阻塞UI

    这就更属于胡扯了,对于一个工作流来说,必须要按着1,2,3的顺序去执行,如果是同步代码,它是一个线程从1执行到3,这个线程将一直被占用!如果是异步代码,它在执行到1时,线程被回收到池子,其它人可以使用,当1执行完成后,从线程池里取出一个新的线程继续执行,这叫异步!C#的异步进行友好,使用async,await就可以实现了!

    实验:查看有效的线程剩余数

            // <summary>
            /// 线程非阻塞,线程利用率高
            /// 线程await后可以去做其它事
            /// 然后await后面方法结束后再申请新线程执行下面的代码
            /// </summary>
            /// <returns></returns>
            [Route("~/do5")]
            public async Task<string> Do5()
            {
                var sw = new Stopwatch();
                sw.Start();
                await HttpHelper.Get("http://localhost:61699/do1");
                await HttpHelper.Get("http://localhost:61699/do2");
                await HttpHelper.Get("http://localhost:61699/do3");
                await HttpHelper.Get("http://localhost:61699/do4");
                sw.Stop();
                int workerThreads, completionPortThreads;
                ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
                return $"max threads:{workerThreads},completionPortThreads:{completionPortThreads},timer:{sw.ElapsedMilliseconds.ToString()}";
            }

    我们来看它的I/O线程剩余,多刷新几次,一直维持在32766和32765之间

    而如果使用同步代码,结果就完成不一样了,线程剩余各位可以看下面

    线程ID在每个await时是不同的

    下面是一个更明显的测试,依次执行多个await,然后获取当前线程的ID,它们在异步环境下,有可能是不同的,因为每次都要从池子里拿新的线程!

                await HttpHelper.Get("http://localhost:61699/do1");
                str.Append($"step1:{Thread.CurrentThread.ManagedThreadId}");
                await HttpHelper.Get("http://localhost:61699/do2");
                str.Append($"step2:{Thread.CurrentThread.ManagedThreadId}");
                await HttpHelper.Get("http://localhost:61699/do3");
                str.Append($"step3:{Thread.CurrentThread.ManagedThreadId}");
                await HttpHelper.Get("http://localhost:61699/do4");
                str.Append($"step4:{Thread.CurrentThread.ManagedThreadId}");

    通过这篇文章,我们应该真正理解异步这个概念了吧,记住,异步主要为了提高线程利用率,从而提高系统的吞吐量的,它与并行,主线程阻塞很有直接关系,也不是它所研究的重点,这个大家一定要记住!

    返回目录

  • 相关阅读:
    java的构造方法 java程序员
    No result defined for action cxd.action.QueryAction and result success java程序员
    大学毕业后拉开差距的真正原因 java程序员
    hibernate的回滚 java程序员
    验证码 getOutputStream() has already been called for this response异常的原因和解决方法 java程序员
    浅谈ssh(struts,spring,hibernate三大框架)整合的意义及其精髓 java程序员
    你平静的生活或许会在某个不可预见的时刻被彻底打碎 java程序员
    Spring配置文件中使用ref local与ref bean的区别. 在ApplicationResources.properties文件中,使用<ref bean>与<ref local>方法如下 java程序员
    poj1416Shredding Company
    poj1905Expanding Rods
  • 原文地址:https://www.cnblogs.com/lori/p/7803113.html
Copyright © 2011-2022 走看看