多线程(一)

异步与多线程 

1.异步和多线程概述

  计算机层面,我们对线程的概念并不陌生,我们打开任务管理器就能看到各种各样的进程,如下图所示

  我们电脑运行的程序我们都能看成一个进程。

  一个程序在运行时使用的全部的计算机资源的合集成为进程。例如我们的QQ音乐就是一个进程。

  同样,我们在任务管理器里面也能看不线程情况,如下图所示

 

  一个程序在响应一个操作是,使用的全部计算机资源合集称为线程。比如我们QQ音乐可以拖动(拖动对应一个线程)、听歌(也对应一个线程)

   那么进程和线程有什么关系呢?线程属于进程,一个进程包含多个线程,线程是计算机执行流的最小单位。

  在程序代码中,我们经常会听到多线程和异步,多线程和异步又是怎样的呢?

  我们先来看下同步和异步的定义。

  同步:发起调用后,要完成当前动作才能进行下一个动作。

  异步:发起调用后,直接进去下一个动作调用,不阻塞,当前动作可以和后续动作并行运行,完成后通知(回调方法)

  

2.多线程使用

  在我们的程序开发中,多线程的使用十分广泛。在winform中,上传文件、提交操作、多线程防止界面卡死等。在web开发中,用户控制发邮件/短信等。

  注意,我们web开发中的ajax方法不是C#的异步,是HTTP请求的异步,发起请求后,可以继续往下执行

  我们接下来实现一个打印功能,来具体看下同步和异步的执行情况

  这是我们一个同步执行方法

private void button1_Click(object sender, EventArgs e)
        {
            Console.WriteLine();
            Console.WriteLine("----------btn_同步 start {0}----------", Thread.CurrentThread.ManagedThreadId);
            for (int i = 0; i < 5; i++)
            {
                string name = string.Format("{0}_{1}", "btn_同步", i);
                print(name);
            }
            Console.WriteLine("----------btn_同步 end {0}----------",Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine();
            Console.ReadLine(); 
        }

这是我们的异步执行方法:

private void button2_Click(object sender, EventArgs e)
        {
            Console.WriteLine();
            Action<string> action = print;
            Console.WriteLine("----------btn_异步start {0}----------", Thread.CurrentThread.ManagedThreadId);
            for(int i=0;i<5;i++)
            {
                string name = string.Format("{0}_{1}","btn_异步",i);
                action.BeginInvoke(name,null,null);
            }
            Console.WriteLine("----------btn_异步end {0}----------", Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine();
            Console.ReadLine(); 
        }

这是我们的打印方法:

public void print(string name)
        {
            Console.WriteLine("线程{0}start {1}",Thread.CurrentThread.ManagedThreadId,DateTime.Now.ToString("HHmmss:ff"));
            int result = 0;
            for (int i = 0; i < 1000000000; i++)
            {
                result += 1;
            }
            Console.WriteLine("线程{0}end {1}",Thread.CurrentThread.ManagedThreadId,DateTime.Now.ToString("HHmmss:ff"));
        }

运行程序的输出结果如下图所示:

  从运行的结果可以看出,多线程执行的总耗时明显比同步执行的少。由此可以看出一定条件下,多线程能提升运行速度。我们理论上,异步执行这里添加了5个线程,理想情况下,异步的执行耗时应该为同步的5分之1.但事实并非如此。主要是因为:

  1.计算机资源有限,并不是5个线程就是5倍的资源。

  2.线程在进行调度的时候也会有时间上的损耗。

  因此,同步方法在执行过程中,只有一个线程执行,速度较异步慢。同步占用的CPU资源少,异步占用的CPU资源多。所以多线程也不是越多越好。

3.异步和多线程的关系

  异步是一种效果,不阻塞,能并行,完成后通知

  多线程是一种手段,多个执行流去完成操作,以达到异步的效果。

  在开发过程中,异步都是通过多线程来实现的。

  异步也可以通过硬件层面来实现(DMP)

4.多线程使用注意事项

我们先来看下下面这两种情况能不能使用多线程。

  1.一个数据库的查询非常耗时,能不能多线程优化下?答案:肯定不能。操作数据库查询任务不能拆分,不能使用多线程。

  2.网站首页包含很多模块,数据接口、数据库查询,读取缓存等等,这种可以通过多线程优化吗?答案:可以的。因为各个模块之间可以拆分,能并行执行,所以可以使用多线程优化

多线程给我们带来方便的同时,也给我们带来了些问题。

从上图异步处理的过程中,我们可以看出,异步执行的顺序是乱的,每次执行的顺序可能都会有差别。因为多线程启动无序、运行无序、结束无序。线程来自操作系统,有自己的调度策略,无法掌控。所以我们在使用时可以控制线程的优先级。优先级的意义在于长期运行会拉开差距。

对于怎么控制线程的执行顺序,我准备下一节内容再介绍了。

原文地址:https://www.cnblogs.com/zxwDont/p/11662418.html