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();