using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
private static object o = new object();
private static Queue<Product> _ProductsNormal { get; set; }
private static Queue<Product> _Products { get; set; }
private static ConcurrentQueue<Product> _ConcurrenProducts { get; set; }
/* -------------------------------------------
* 对比lock锁和ConcurrentQueue并发性能
* -------------------------------------------
在.NET Framework4.0以后的版本中提供了命名空间:System.Collections.Concurrent 来解决线程安全和lock锁性能问题,通过这个命名空间,能访问以下为并发做好了准备的集合。
1.BlockingCollection 与经典的阻塞队列数据结构类似,能够适用于多个任务添加和删除数据,提供阻塞和限界能力。
2.ConcurrentBag 提供对象的线程安全的无序集合
3.ConcurrentDictionary 提供可有多个线程同时访问的键值对的线程安全集合
4.ConcurrentQueue 提供线程安全的先进先出集合
5.ConcurrentStack 提供线程安全的后进先出集合
这些集合通过使用比较并交换和内存屏障等技术,避免使用典型的互斥重量级的锁,从而保证线程安全和性能。
*/
static void Main(string[] args)
{
#region 不启用并行计算使用锁lock
//休眠重置校准结果
Thread.Sleep(1000);
_ProductsNormal = new Queue<Product>();
Stopwatch swTaskn = new Stopwatch();//用于统计时间消耗的
swTaskn.Start();
Task tn1 = Task.Factory.StartNew(() => { AddProductsNormal(); });
Task tn2 = Task.Factory.StartNew(() => { AddProductsNormal(); });
Task tn3 = Task.Factory.StartNew(() => { AddProductsNormal(); });
Task tn4 = Task.Factory.StartNew(() => { AddProductsNormal(); });
Task tn5 = Task.Factory.StartNew(() => { AddProductsNormal(); });
Task.WaitAll(tn1, tn2, tn3, tn4, tn5);
swTaskn.Stop();
Console.WriteLine("=========================不启用并行计算使用锁lock==================================");
Console.WriteLine("Queue<Product> 当前数据量为:" + _ProductsNormal.Count);
Console.WriteLine("Queue<Product> 执行时间为:" + swTaskn.ElapsedMilliseconds);
#endregion
#region 启用并行计算使用锁lock
//休眠重置校准结果
Thread.Sleep(1000);
_Products = new Queue<Product>();
Stopwatch swTask = new Stopwatch();//用于统计时间消耗的
swTask.Start();
Task t1 = Task.Factory.StartNew(() => { AddProducts(); });
Task t2 = Task.Factory.StartNew(() => { AddProducts(); });
Task t3 = Task.Factory.StartNew(() => { AddProducts(); });
Task t4 = Task.Factory.StartNew(() => { AddProducts(); });
Task t5 = Task.Factory.StartNew(() => { AddProducts(); });
Task.WaitAll(t1, t2, t3, t4, t5);
swTask.Stop();
Console.WriteLine("=========================启用并行计算使用锁lock==================================");
Console.WriteLine("Queue<Product> 当前数据量为:" + _Products.Count);
Console.WriteLine("Queue<Product> 执行时间为:" + swTask.ElapsedMilliseconds);
#endregion
#region 启用并行计算不使用锁,使用4.0后提供的新功能
//休眠重置校准结果
Thread.Sleep(1000);
_ConcurrenProducts = new ConcurrentQueue<Product>();
Stopwatch swTask1 = new Stopwatch();
swTask1.Start();
Task tk1 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
Task tk2 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
Task tk3 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
Task tk4 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
Task tk5 = Task.Factory.StartNew(() => { AddConcurrenProducts(); });
Task.WaitAll(tk1, tk2, tk3, tk4, tk5);
swTask1.Stop();
Console.WriteLine("===========启用并行计算不使用锁,使用4.0后提供的新功能==============================");
Console.WriteLine("ConcurrentQueue<Product> 当前数据量为:" + _ConcurrenProducts.Count);
Console.WriteLine("ConcurrentQueue<Product> 执行时间为:" + swTask1.ElapsedMilliseconds);
#endregion
Console.ReadLine();
}
static void AddProductsNormal()
{
for (int i = 0; i < 1000000; i++)
{
Product product = new Product() { Name = "name" + i, Category = "Category" + i, SellPrice = 1 };
lock (o)
{
_ProductsNormal.Enqueue(product);
}
}
}
static void AddProducts()
{
Parallel.For(0, 1000000, (i) =>
{
Product product = new Product() { Name = "name" + i, Category = "Category" + i, SellPrice = 1 };
lock (o)
{
_Products.Enqueue(product);
}
});
}
static void AddConcurrenProducts()
{
Parallel.For(0, 1000000, (i) =>
{
Product product = new Product() { Name = "name" + i, Category = "Category" + i, SellPrice = 1 };
_ConcurrenProducts.Enqueue(product);
});
}
}
class Product
{
public string Name { get; set; }
public string Category { get; set; }
public int SellPrice { get; set; }
}
}
/*
Parallel在循环中的每个任务很简单,耗时很小时,并不具备优势,反而因为多线程开销导致效率低下。
但在每个任务耗时较大时,应该使用Parallel,实现并发,具备很大的优势
*/
var dt = DateTime.Now;
var rand = new Random();
for (int i = 0; i < 200; i++)
{
Thread.Sleep(rand.Next(10, 100));
}
var standerTime = (DateTime.Now - dt).TotalMilliseconds;
Console.WriteLine("标准的for循环,耗时{0}毫秒", standerTime);
dt = DateTime.Now;
int count = 0;
Parallel.For(0, 200, i =>
{
//轻量级锁
Interlocked.Increment(ref count);
Thread.Sleep(rand.Next(10, 100));
});
Console.WriteLine("循环次数" + count);
var parallelTime = (DateTime.Now - dt).TotalMilliseconds;
Console.WriteLine("并行的for循环,耗时{0}毫秒", parallelTime);
Console.WriteLine();
if (standerTime <= parallelTime)
{
Console.WriteLine("----------标准的for循环节省{0}毫秒----------", (parallelTime - standerTime));
}
else
{
Console.WriteLine("----------并行的for循环节省{0}毫秒----------", (standerTime - parallelTime));
}
//Console.WriteLine(result.Result.ToString());
Console.ReadLine();