一. 并行编程

1. 区分串行编程和串行编程

  ①. 串行编程:所谓的串行编程就是单线程的作用下,按顺序执行。(典型代表for循环 下面例子从1-100按顺序执行)

  ②. 并行编程:充分利用多核cpu的优势,同时开启多个线程并行执行。(典型代表Parallel.For循环 下面例子从1-100无序执行)

 代码实践:

   {
//1. 串行 (从1-100按顺序执行)
for (int i = ; i < ; i++)
{
Console.WriteLine(i);
}
//2. 并行 (从1-100无序执行)
Parallel.For(, , (item) =>
{
Console.WriteLine(item);
});
}

结论:串行的代码按顺序依次输出,并行的代码无顺序输出。

2. 深究Parallel类中的方法 (For方法、ForEach方法、Invoke方法 这三个方法都是用来开启线程的)

(1). Invoke方法

  a. 该方法的作用就是用来同时开启多个线程的。

  b. 该方法有两个重载,主要涉及到两个参数,用来配置最大并行数(即线程数)和一个可变的Action委托数组(详见源码)。

案例一: 开启五个不同的线程调用五个方法

我们发现一个现象,主线程等着这五个子线程执行完毕后才执行,但是我们并没有写线程等待的代码,所以我们可以总结:

①:并行计算,开启多个线程后,不需要再开辟线程等待,直接是主线程完成后续操作。

②:而普通多线程执行后,需要单独再开辟一个线程等待,然后主线程在执行。

 代码实践:

                 {
Parallel.Invoke(() => this.TestThread("bct1")
, () => this.TestThread("bct2")
, () => this.TestThread("bct3")
, () => this.TestThread("bct4")
, () => this.TestThread("bct5")
);
}

案例二: 指定最大并行数进行线程调用

我们发现,五个任务中的四个任务同时由不同线程开启,当其中一个任务结束时,第五个任务开启,并由刚结束的任务的线程来执行。

                {
//设置最大的线程并行数
ParallelOptions p = new ParallelOptions();
p.MaxDegreeOfParallelism = ; Parallel.Invoke(p, () => this.TestThread("bct1")
, () => this.TestThread("bct2")
, () => this.TestThread("bct3")
, () => this.TestThread("bct4")
, () => this.TestThread("bct5")
);
}

(2). For方法 (前两个参数之间的差代表任务的个数)

  这里介绍一个简单重载: public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body);

  fromInclusive:开始索引(含).

  toExclusive:结束索引(不含).

  body:将为每个迭代调用一次的委托.

当然该方法中的其他重载中也有很丰富的功能,比如也可以配置最大线程数。

代码实践:

  {
//案例一:前两个参数之间的差,就为并行计算线程的个数
{
Parallel.For(, , t =>
{
//这里的t分别为:5,6,7,8,9 五个数
string name = string.Format("bct{0}", t);
this.TestThread(name);
});
}
//案例二: 配置最大并行数
//结果:同时最多5个线程执行,但是还是要执行9个任务,(6,7,8,9,10,11,12,13,14),后面四个任务等前面的执行完后,再执行
{
ParallelOptions po = new ParallelOptions()
{
MaxDegreeOfParallelism = //表示最大线程数为5,后面即使配置超过5,也无效
};
Parallel.For(, , po, (t, state) =>
{
string name = string.Format("bct{0}", t);
this.TestThread(name);
//state.Break(); //退出单次循环(没看到实际作用)
// state.Stop(); //退出全部循环(没看到实际作用)
//return;
});
}
}

(3). ForEach方法

  这里也是介绍一个简单的重载:int数组中的个数代表需要进行并行任务的个数,但并不一定所有任务同时执行,也不一定每个任务都是一个新线程执行。

该方法当然也可以配置最大并行数。

 代码实践:

 {
//数组里的个数,就为并行进行并行任务数
Parallel.ForEach(new int[] { , , , , }, t =>
{
//这里的t分别为:3, 5, 44, 55, 100五个数
string name = string.Format("bct{0}", t);
this.TestThread(name);
}
}

二. 常见的编程模型

1.同步编程模型(SPM):单线线程、串行开发模式。

2.异步编程模型(APM):xxxbegin、xxxend的模式。

3.基于事件的编程模型(EAP): xxAsync这样的事件模式。 eg:WebClient。

4.基于Task的编程模型(TAP): APM和EAP都可以使用Task来实现,微软的初衷就是想通过Task大一统异步编程领域。

下面分享两段代码,不做深入研究了。

             {
FileStream fs = new FileStream(Environment.CurrentDirectory + "//1.txt", FileMode.Open);
var bytes = new byte[fs.Length];
var task = Task.Factory.FromAsync(fs.BeginRead, fs.EndRead, bytes, , bytes.Length, string.Empty); var nums = task.Result; Console.WriteLine(nums);
}
{
FileStream fs = new FileStream(Environment.CurrentDirectory + "//1.txt", FileMode.Open); var bytes = new byte[fs.Length]; fs.BeginRead(bytes, , bytes.Length, (aysc) =>
{
var nums = fs.EndRead(aysc); Console.WriteLine(nums); }, string.Empty); Console.Read();
}

第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)的更多相关文章

  1. Android 编程 AMapLocationClientOption 类中的 setNeedAddress 方法用处 (高德地图 com.amap.api.location.AMapLocationClientOption 中的类)

    最近在用高德地图来写Android App, 其中有一些 方法是不太理解的,这里写一下 对  高德地图  com.amap.api.location.AMapLocationClientOption ...

  2. 第8.6节 Python类中的__new__方法深入剖析:调用父类__new__方法参数的困惑

    上节<第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解>通过案例详细分析了两个方法的执行顺序,不知大家是否注意到了,在上述 ...

  3. 第8.26节 重写Python类中的__getattribute__方法实现实例属性访问捕获

    一. 引言 在<第7.23节 Python使用property函数定义属性简化属性访问的代码实现>和<第7.26节 Python中的@property装饰器定义属性访问方法gette ...

  4. Java中是否可以调用一个类中的main方法?

    前几天面试的时候,被问到在Java中是否可以调用一个类中的main方法?回来测试了下,答案是可以!代码如下: main1中调用main2的主方法 package org.fiu.test; impor ...

  5. 重写Object类中的equals方法

    Object是所有类的父亲,这个类有很多方法,我们都可以直接调用,但有些方法并不适合,例如下面的student类 public class Student { //姓名.学号.年纪 private S ...

  6. PHP通过反射方法调用执行类中的私有方法

    PHP 5 具有完整的反射 API,添加了对类.接口.函数.方法和扩展进行反向工程的能力. 下面我们演示一下如何通过反射,来调用执行一个类中的私有方法: <?php //MyClass这个类中包 ...

  7. Java String类中的intern()方法

    今天在看一本书的时候注意到一个String的intern()方法,平常没用过,只是见过这个方法,也没去仔细看过这个方法.所以今天看了一下.个人觉得给String类中加入这个方法可能是为了提升一点点性能 ...

  8. Java线程状态及Thread类中的主要方法

    要想实现多线程,就必须在主线程中创建新的线程对象. 不论什么线程一般具有5种状态,即创建,就绪,执行,堵塞,终止. 创建状态: 在程序中用构造方法创建了一个线程对象后,新的线程对象便处于新建状态,此时 ...

  9. [SignalR]在非Hub继承类中使用脚本方法

    原文:[SignalR]在非Hub继承类中使用脚本方法 新建一个普通类OutHub,里面包含一个脚本方法OutHubTest. 因为大家知道,若能让脚本调用到的话,必须继承Hub,那怎么实现了?通过G ...

随机推荐

  1. python 结巴分词学习

    结巴分词(自然语言处理之中文分词器) jieba分词算法使用了基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能生成词情况所构成的有向无环图(DAG), 再采用了动态规划查找最大概率路径,找出基于 ...

  2. 修改json对象的每一个值

    function fun1(obj){ var names={}; /*for in 可以用于数组或者对象*/ for(var name in obj){ names[name] = obj[name ...

  3. 关键字-super

    super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类. class BaseAction { String name; int age; void value( ...

  4. Linux-基础学习(五)-mariadb主从复制以及redis学习

    开始今日份整理 1.mariadb的主从复制 主从复制大致图示: 1.1 mysql基本命令复习 linux下的操作 .启动mysql systemctl start mariadb .linux客户 ...

  5. (三)Installation

    Elasticsearch requires at least Java 8. Specifically as of this writing, it is recommended that you ...

  6. C# 对文本文件的几种读写方法总结

    计算机在最初只支持ASCII编码,但是后来为了支持其他语言中的字符(比如汉字)以及一些特殊字符(比如€),就引入了Unicode字符集.基于Unicode字符集的编码方式有很多,比如UTF-7.UTF ...

  7. Python的dnspython库使用指南

    因为平时在测试DNS的时候有些操作手动完成不方便,所以需要用到脚本,而在Python里dnspython这个用于DNS操作的库十分强大,但是无奈网上大部分资料只列举了少部分的用法,所以记录一下我平时使 ...

  8. Neutron :默认通过 dnsmasq 实现 DHCP 功能----Namespace

    Neutron 提供 DHCP 服务的组件是 DHCP agent. DHCP agent 在网络节点运行上,默认通过 dnsmasq 实现 DHCP 功能.   配置 DHCP agent DHCP ...

  9. YCD 软件更新方法

    备份Messenger的数据库和Player的Chainmail数据 Upgrade process in Cnario is quite simple, uninstall old version ...

  10. 如何升级centos到最新版本

    本文将教你如何升级centos到最新版本.centos中“update”命令可以一次性更新所有软件到最新版本.注意:不推荐使用update的y选项,-y选项会让你在安装每项更新前都进行确认(译者注:这 ...