首页 > 其他分享 >异步VS多线程

异步VS多线程

时间:2024-03-26 16:12:05浏览次数:20  
标签:异步 Console Thread VS 线程 多线程 ID

前段时间面试的时候被问到了异步和多线程的区别,回答的模棱两可,今天花时间系统的了解了下,如有错误,欢迎斧正~

异步与多线程是在并发编程中两个比较关键的概念, 很容易弄混淆:

异步编程(Asynchronous)

概念:异步编程是并发编程的一种形式,即在程序运行逻辑中,一部分语句可以独立于主程序而执行。

理解:异步相对于同步而言,同步的模式很容易理解,假设一块程序只有十步逻辑,那么这段逻辑中每步代码都要等待前一步代码执行完成才会执行,换句话说就是主程序流是从上往下依次顺序执行的,如果遇到一个步骤,常见的是我们对后端一个请求或一次数据访问,这个操作往往耗时很久(这个操作我们称之为一个阻断操作),整个页面就会停在那里没有响应。为了提高页面的体验度,异步请求应运而生。

使用目的:为了提高用户体验,优化页面加载。

关键字:在C#中,异步编程通过关键字asyncawait来达成。

多线程编程(Multithreading)

概念:多线程就是CPU利用多个线程来并发地运行多段逻辑。

理解:在计算机科学中,一个线程指的是在程序中一段连续的逻辑控制流。在业务很复杂的时候,一个线程无法满足现有业务需求,多线程编程就应运而生。

使用目的:为了最大限度地利用多核CPU这个硬件条件来达到多个线程同时执行逻辑。

关键字:在C#中,System.Threading命名空间下有很多类用来进行多线程编程。

异步VS多线程

一个常见的概念混淆就是吧异步和多线程当成一回事,其实不一样。异步侧重于任务的执行顺序,而多线程则是关于多个线程如何并发执行。应该说多线程是实现异步的常用手段,但不能说他们是一回事。即便是只有一个线程的情况下。我们仍然可以实现异步。

举例说明两者的区别:

首先来看异步编程的代码:

        public static async Task FirstAsync()
        {
            Console.WriteLine($"第一个异步方法开始,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(2000);
            Console.WriteLine($"第一个异步方法结束,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
        }
        public static async Task SecondAsync()
        {
            Console.WriteLine($"第二个异步方法开始,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(2000);
            Console.WriteLine($"第二个异步方法结束,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
        }
        public static async Task ThirdAsync()
        {
            Console.WriteLine($"第三个异步方法开始,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(2000);
            Console.WriteLine($"第三个异步方法结束,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
        }

我们这里定义了三个异步方法,在每个异步方法中,我们在任务开始执行的时候在控制台打印出线程ID,然后通过延时两秒钟来模拟业务逻辑,最后我们依然打印出线程ID。

然后,添加一个异步方法来调用上面的异步方法:

        public static async Task ExecuteAysnc()
        {
            var firstAsync = FirstAsync();
            var secondAsync = SecondAsync();
            var thirdAsync = ThirdAsync();
            await Task.WhenAll(firstAsync, secondAsync, thirdAsync);
        }

最后在Main方法中调用执行方法:

        public static async Task ExecuteAysnc()
        {
            var firstAsync = FirstAsync();
            var secondAsync = SecondAsync();
            var thirdAsync = ThirdAsync();
            await Task.WhenAll(firstAsync, secondAsync, thirdAsync);
        }

运行结果如下:

 从运行结果可以看出:所有三个异步方法都是在线程ID为1的线程上运行的,但是经过2秒钟的睡眠,当再次执行异步任务的时候,每个任务又被别的线程执行起来,这里显示为4、7、5.

为什么会发生这样的事情呢?原因就在于当线程发现关键字await的时候该线程就会从当前逻辑释放而返回给线程池。一旦睡眠结束,一个新的线程(4、7、5)就重新被分配来执行三个任务。

同样地,我们再看看多线程的代码示例,与上面的例子不同,我们去除了关键字async

        public static  void FirstMethod()
        {
            Console.WriteLine($"第一个方法开始,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(2000);
            Console.WriteLine($"第一个方法结束,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
        }
        public static void SecondMethod()
        {
            Console.WriteLine($"第二个方法开始,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(2000);
            Console.WriteLine($"第二个方法结束,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
        }
        public static void ThirdMethod()
        {
            Console.WriteLine($"第三个方法开始,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(2000);
            Console.WriteLine($"第三个方法结束,运行的线程ID为:{Thread.CurrentThread.ManagedThreadId}");
        }

逻辑和异步方法的一样,都是在开始的时候打印线程ID,2秒的业务逻辑操作之后再打印当前线程ID,同样,我们创建一个方法,再这个方法里,开启三个线程来启动这三个任务:

        public static void ExecuteMultithreading()
        {
            Thread firstThread = new Thread(() => FirstMethod());
            Thread secondThread = new Thread(() => SecondMethod());
            Thread thirdThread = new Thread(() => ThirdMethod());

            firstThread.Start();
            secondThread.Start();
            thirdThread.Start();
        }

main函数调用执行方法:

        static void Main(string[] args)
        {
            Multithreading.ExecuteMultithreading();
            Console.ReadLine();
        }

运行结果如下:

 从打印结果可以看出,同一个方法,开始和结束的线程ID保持一致。再多线程的例子里,我们显示地分配了线程,该线程直到做完对应的任务才会结束,即时逻辑当中有一段时间的业务逻辑。

使用场景:

现在我们明白了异步和多线程的差别,下面我们可以得出:

异步编程适用场景

  1. 我们的程序逻辑中存在阻断操作。
  2. 我们的应用有一个线程池并且有垂直扩展的需求。

多线程编程适用场景:

  1. 我们的程序逻辑存在相互独立的任务,任务与任务之间不相互干扰。
  2. 我们存在多个可用的CPU内核数。

总结:

异步编程和多线程编程的区别在于侧重点不同,异步编程侧重于任务的执行顺序,而多线程编程则是关于多个线程如何并发执行最大限度利用CPU,两者对于提高程序可用性和性能方面起到了关键性的作用。

标签:异步,Console,Thread,VS,线程,多线程,ID
From: https://www.cnblogs.com/jiangxianshen/p/18096429

相关文章

  • 【问题处理】cannot register qt5vs vs2010 help
    问题描述:安装qt-vs-addin-1.2.4-opensource时,在安装过程中弹出错误窗口,错误信息为cannotregisterqt5vsvs2010help;安装完成后,打开VS2010无法使用插件。解决方案:Window10搜索cmd并使用管理员身份运行,随后输入如下命令"C:\ProgramFiles(x86)\MicrosoftSDKs\Windows\v7......
  • 写请求异步化方案
    参考:https://news.sohu.com/a/566698836_121124376https://www.cnblogs.com/maohuidong/p/17147870.html方向:减少写动作的耗时,提升写动作的并发度1、优化sql,分库分表,提高数据库配置2、线程池 3、本地内存+定时任务 4、MQ 5、代理服务 ......
  • VsCode安装,配置,快捷键及常用开发插件的安装与介绍
    目录一.安装包下载方式一.官网下载方式二.网盘下载二.安装三.VSCode插件安装1.中文语言包2.拼写检察器3.HTML自动补全4.JavaScript-ES6语法提示5.补全前端代码6.路径提示7.Vue3/Vue2开发必用8.自动闭合HTML/XML标签9.标签同步修改10.格式化html,css,js11.区分括号12.快速打开html1......
  • 爬虫之多任务异步协程
    gevent模块示例代码:特点:可以识别所有阻塞fromgeventimportmonkeymonkey.patch_all()importgeventimportrequestsfromlxmlimportetreeimporttime#发送请求defget_request(url):page_text=requests.get(url).texttree=etree.HTML(page_text)......
  • 强大的VS插件CodeRush全新发布v23.2.6——支持语音
    CodeRush是一个强大的VisualStudio.NET插件,它利用整合技术,通过促进开发者和团队效率来提升开发者体验。CodeRushv23.2.6正式版下载具体更新详情如下:语音支持-CTP指定Azure语音识别和OpenAIAPI密钥后,可以在VisualStudio2022中启用语音功能。语音命令按住Ctrl键并说......
  • 异步通知和MISC设备驱动
    异步通知:驱动程序中的异步通知是指驱动程序可以向应用程序发送通知,告知应用程序发生了某种事件。这种通知是异步的,即应用程序可以继续执行其他操作,而不需要主动轮询或等待事件的发生。在Linux内核中,实现驱动异步通知的一种常见方式是使用fasync机制。这个机制的核心是利用fasync......
  • Mac 使用VSCode搭建SpringBoot+Maven开发环境
    Mac使用VSCode搭建SpringBoot+Maven开发环境大多数人在开发java后端时使用的是IntelliJIDEA,该软件商用版收费太贵,社区版功能又太少,所以我希望可以使用VSCode来创建和开发后端项目,搭建的过程如下:1.下载和安装javasdk下载地址:https://www.oracle.com/java/technologies/downl......
  • 掌握C#中异步魔法:同步方法如何优雅调用异步方法
     概述:上述C#示例演示了如何在同步方法中调用异步方法。通过使用`async`和`await`关键字,实现了同步方法对异步方法的调用。建议使用`await`而不是`Result`来避免潜在的死锁问题。这种模式在处理异步任务时能够提高代码的可读性和性能。在C#中,从同步方法调用异步方法的过程涉及......
  • Vs Code中运行vue命令显示"系统禁止运行脚本"无法在终端使用
    右键点击vscode中的属性,在上面找到兼容性一栏,勾选里面以管理员身份运行在当前电脑中搜索WindowsPowerShell以管理员的身份运行 在里面输入 set-ExecutionPolicyRemoteSigned选择权限A ......
  • 异步秒杀场景下消息队列如何防止消息丢失
    1、生产者写入消息时使用确认机制。生产者向写入消息时,写入成功则消息队列给生产者返回一个成功标识,写入失败,则返回一个失败标识,然后生产者通过失败重试机制重新写入消息。2、将消息队列中的消息持久化到磁盘中3、手动确认机制允许消费者对接收到的每一条消息进行确认,从而确......