关于Parallel我也不细说了,一则微软封装的很好用,二来介绍这个的遍地都是。

  我要说的是,要想成为一个优秀的标题党,一定要把重点放到别的地方,为了节省大家阅读时间,我先把结论说了,然后再慢慢从头说,愿意往下看的可以看看因果,不愿意看的,也算咱给大家提个醒吧。

  结论就是,大家在做单元测试用例的时候一定要用心,这篇随笔是要检讨并警醒下自己并与大家共勉。

  据一些我不记得名字的国外权威专家,据说是测试大师级人物研究,测试用例的出现的错误并不比被测试的代码少,我相信大多数人会和我类似,在写代码的时候小心翼翼,但是为代码编写单元测试及用例的时候往往注意力下意识的不那么集中,今天就是这么个情况。可能是缺乏锻炼(我天天打太极拳的。。。)的原因,连续几个晚上由于学习原因睡的比较晚,今天就比较困,然后干了件点题的事。

  我写了一个对象ID生成器,以时间戳和顺序号组合,虽然不支持集群,但是目前情况下足够了,然后因为复制数据库的同事坚决不同意将主键的int类型改掉,那怕改成bigint都不同意。。。跑题了。总之,各种限制的情况下出了这么个东西:

  //不能再集群情况下使用
public class IDGenerator
{
     private static double _seconds = 0;
private static int _sequenceIndex = 0;
private static object _lock = new object();
     private static ReaderWriterLockSlim writerLock = new ReaderWriterLockSlim();
private static IDGenerator _instance; private IDGenerator()
{
} public static int NewID
{
get
{
int newID = IDGenerator.Instance.CreateNewID();
return newID;
}
} private int CreateNewID()
{
string id; writerLock.EnterReadLock();
try
{
id = BuildIDAndUpdateSead();
}
finally//保证退出锁
{
writerLock.ExitReadLock();
}
int newID = TypeParseHelper.GetIntValueByString(id);
return newID;
} private string BuildIDAndUpdateSead()
{
double seconds;
bool isEqualSecondsCount;
seconds = InterceptSecondsInTicks(); isEqualSecondsCount = seconds.Equals(_seconds);
if (isEqualSecondsCount)
{
         bool isUpperBound = _sequenceIndex == ;
if (isUpperBound)
{
Thread.Sleep();
_sequenceIndex = ;
_seconds++;
}
          else
          {
  Interlocked.Increment(ref _sequenceIndex);
          }
}
else
            {
_seconds = seconds;
}
string id = _seconds.ToString() + _sequenceIndex.ToString().PadLeft(, '');
return id;
} private double InterceptSecondsInTicks()
{
DateTime currentDate = DateTime.Now;
long elapsedTicks = (currentDate.Ticks - ConstantGather.BEGIN_STANDARD_TICKS);
TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
double seconds = Math.Floor(elapsedSpan.TotalSeconds);
return seconds;
} private static IDGenerator Instance
{
get
{
if (_instance != null)
{
return _instance;
} lock (_lock)
{
if (_instance == null)
{
_instance = new IDGenerator();
}
} return _instance;
}
}
}

  做完了,当然要写点单元测试测试一下,就先写了个同步的,然后写了个异步的,然后写了个并发的

       public List<int> GenerateRequisitionIDs()
{
TaskFactory taskFactory = new TaskFactory();
Task<int>[] tasks = new Task<int>[] {
taskFactory.StartNew(() => GenerateRequisitionID()),
taskFactory.StartNew(() => GenerateRequisitionID()),
taskFactory.StartNew(() => GenerateRequisitionID()) }; var query = tasks.Where(t => !t.Result.Equals())
.Select(t => t.Result);
return query.ToList();
}

  高潮来了,然后我在单元测试里顺手写了个并行的。。。

Parallel.For(, actual, c =>
{
int id = target.GenerateRequisitionID();
list.AddLast(id);
});

  测试结果就不停得出错,我费了很大功夫定位到了出错的位置。。。

string idStr = _seconds.ToString() + "-" + _sequenceIndex.ToString().PadLeft(, '');

  这一句是我写了一堆定位错误的代码中的一句,发现了个奇怪的现象,这个字符串赋值后,两边居然是不一样的,而且这一句在排它锁里。。。

  并行的用法应该是将一对任务,平均分开,各自做各自的,互相不影响,问题就在于我这生成器是个单例。。。

  作为一个敬业的标题党,并发和并行的区别我就不说了,反正连百度都知道的事。。。  

  最后说一句,单元测试要认真,单元测试的代码哪怕随便玩的也要组织好,不要乱放,不要完全不着边的都测,正常业务里是不会有并行生成ID的场景的,这个测试没有意义,而且,如果看了生成器的代码会发现,由于int32本身的长度问题,我限定了一秒最多能生成999个ID,我需要测的其实不是并行问题,太晚了,思维比较跳跃,就这么着吧,下次长点记性就好了,以上。

Parallel并行之乱用的更多相关文章

  1. Parallel并行编程初步

    Parallel并行编程可以让我们使用极致的使用CPU.并行编程与多线程编程不同,多线程编程无论怎样开启线程,也是在同一个CPU上切换时间片.而并行编程则是多CPU核心同时工作.耗时的CPU计算操作选 ...

  2. C# IEnumerable,Lambda表达式和 Parallel并行编程的用法

    以前一直主要做C++和C方面的项目,对C#不太了解熟悉,但听说不难,也就一直没有在意学习C#方面的知识.今天有个C#项目,需要做些应用的扩展,同时修改一些bug.但看了C#代码,顿时觉得有些不适应了. ...

  3. Parallel并行编程

    Parallel并行编程 Parallel并行编程可以让我们使用极致的使用CPU.并行编程与多线程编程不同,多线程编程无论怎样开启线程,也是在同一个CPU上切换时间片.而并行编程则是多CPU核心同时工 ...

  4. C# 使用Parallel并行开发Parallel.For、Parallel.Foreach实例

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.N ...

  5. list.stream().parallel() 并行流

    https://blog.csdn.net/u011001723/article/details/52794455/  :  parallel()其实就是一个并行执行的流.它通过默认的ForkJoin ...

  6. Stream parallel并行流的思考

    1.并行流并不一定能提高效率,就和多线程并不能提高线程的效率一样 因为引入并行流会引起额外的开销,就像线程的频繁上下文切换会导致额外的性能开销一样,当数据在多个cpu中的处理时间小于内核之间的传输时间 ...

  7. .net Parallel并行使用注意事项

    因项目响应过慢,代码优化空间不大,在暂时无法调整系统架构的情况下,只有使用.NET中的TPL解决一些模块耗时过多的问题.但在使用过程中也碰到了一些问题,现在把它写下来,用于备忘. 1. Paralle ...

  8. .net Parallel并行使用

    因项目响应过慢,代码优化空间不大,在暂时无法调整系统架构的情况下,只有使用.NET中的TPL解决一些模块耗时过多的问题.但在使用过程中也碰到了一些问题,现在把它写下来,用于备忘. 1. Paralle ...

  9. oracle使用parallel并行,多线程查询

    insert into tmp (select /*parallel (a, 4)*/ * from plsuer.as_cdrindex_info_h partition(P_20170430) w ...

随机推荐

  1. NodeJs之log4js

    log4js log4js是一个管理,记录日志的工具. 其实与morgan的作用类似. 安装 npm install -g log4js log4js的6个日志级别 分别是:trace(蓝色).deb ...

  2. EntityFramework Core 1.1是如何创建DbContext实例的呢?

    前言 上一篇我们简单讲述了在EF Core1.1中如何进行迁移,本文我们来讲讲EF Core1.1中那些不为人知的事,细抠细节,从我做起. 显式创建DbContext实例 通过带OnConfiguri ...

  3. spring源码分析之freemarker整合

    FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个Java类库,是一款程 ...

  4. 【C#附源码】数据库文档生成工具支持(Excel+Html)

    [2015] 很多时候,我们在生成数据库文档时,使用某些工具,可效果总不理想,不是内容不详细,就是表现效果一般般.很多还是word.html的.看着真是别扭.本人习惯用Excel,所以闲暇时,就简单的 ...

  5. CentOS下mysql数据库常用命令总结

    mysql数据库使用总结 本文主要记录一些mysql日常使用的命令,供以后查询. 1.更改root密码 mysqladmin -uroot password 'yourpassword' 2.远程登陆 ...

  6. go语言:多个[]byte数组合并成一个[]byte

    场景:在开发中,要将多个[]byte数组合并成一个[]byte,初步实现思路如下: 1.获取多个[]byte长度 2.构造一个二维码数组 3.循环将[]byte拷贝到二维数组中 package gst ...

  7. Twproject Gantt开源甘特图功能扩展

    1.Twproject Gantt甘特图介绍 Twproject Gantt 是一款基于 jQuery 开发的甘特图组件,也可以创建其它图表,例如任务树(Task Trees).内置编辑.缩放和 CS ...

  8. BPM流程中心解决方案分享

    一.需求分析 在过去办公自动化的浪潮中,很多企业已经实施了OA流程,但随着客户的发展和对流程管理的越来越重视, 客户对流程应用需求越来越深 入,您可能面临以下需求: 1.流程功能不能满足需求,包括流程 ...

  9. Linux实战教学笔记06:Linux系统基础优化

    第六节 Linux系统基础优化 标签(空格分隔):Linux实战教学笔记-陈思齐 第1章 基础环境 第2章 使用网易163镜像做yum源 默认国外的yum源速度很慢,所以换成国内的. 第一步:先备份 ...

  10. 用javascript写星际飞机大战游戏

    在github里看到了个不错的脚本游戏,决定亲自动手来写,效果如下 下面是代码的思路分享 把整个代码理解消化确实不容易,但是如果你坚持看完相信你一定会有收获 如果没兴趣可以直接点击下面的链接 复制代码 ...