1、代码如下
// *********************************************************************** // Assembly : Share.Code.MultiThreadTest // Author : zhujinrong // Created : 11-20-2014 // // Last Modified By : zhujinrong // Last Modified On : 11-20-2014 // *********************************************************************** // <copyright file="SumMultiThread2.cs" company="Microsoft"> // Copyright (c) Microsoft. All rights reserved. // </copyright> // <summary></summary> // *********************************************************************** using System; using System.Collections.Generic; using System.Threading; namespace Share.Code.MultiThreadTest { /// <summary> /// 多线程求和 /// </summary> public class SumMultiThread2 {
/// <summary>
/// 锁
/// </summary>
static object lockObj = new object();
/// <summary> /// 子线程数量 /// </summary> private int threadNum = 0; /// <summary> /// 待处理数据 /// </summary> private List<int> dataList = new List<int>(); /// <summary> /// 通知一个线程或多个线程正在发生的事情 /// </summary> private List<ManualResetEvent> manualEventList = new List<ManualResetEvent>(); /// <summary> /// 自动重置同步事件数组 /// </summary> private AutoResetEvent[] autoEvents; /// <summary> /// 初始化同步事件 /// </summary> private List<AutoResetEvent> tempEvents = new List<AutoResetEvent>(); /// <summary> /// 手动重置同步事件 /// </summary> private ManualResetEvent manualEvent; /// <summary> /// 子线程结果 /// </summary> private List<long> subSumList = new List<long>(); /// <summary> /// 子线程结果 /// </summary> private Dictionary<int, long> resultList = new Dictionary<int, long>(); /// <summary> /// 构造函数 /// </summary> /// <param name="dataList">数据</param> /// <param name="threadNum">线程个数</param> public SumMultiThread2(List<int> dataList, int threadNum) { this.dataList = dataList; this.threadNum = threadNum; for (int i = 0; i < this.threadNum; i++) { this.tempEvents.Add(new AutoResetEvent(false)); } this.autoEvents = this.tempEvents.ToArray(); this.manualEvent = new ManualResetEvent(false); } /// <summary> /// 执行结果 /// </summary> public long Result { get; private set; } /// <summary> /// 执行 /// </summary> public void Execute() { if (this.dataList == null || this.dataList.Count == 0 || this.threadNum == 0) { return; } ThreadPool.QueueUserWorkItem(new WaitCallback(this.SetManualEvent)); // 给每个线程分配数据 List<List<int>> list = new List<List<int>>(); for (int i = 0; i < this.threadNum; i++) { list.Add(new List<int>()); } for (int i = 0; i < this.dataList.Count; i++) { list[i % this.threadNum].Add(this.dataList[i]); } for (int i = 0; i < this.threadNum; i++) { Dictionary<int, List<int>> dic = new Dictionary<int, List<int>>(); dic.Add(i, list[i]); ThreadPool.QueueUserWorkItem(new WaitCallback(this.ExecuteSum), dic); } // 等待所有自动事件终止 WaitHandle.WaitAll(this.autoEvents); long sum = 0; foreach (var item in this.resultList) { sum += item.Value; } this.Result = sum; } /// <summary> /// 具体执行 /// </summary> /// <param name="obj">对象</param> private void ExecuteSum(object obj) { DateTime start = DateTime.Now; DateTime end = DateTime.Now; Dictionary<int, List<int>> dic = obj as Dictionary<int, List<int>>; int index = 0; foreach (var item in dic) { index = item.Key; long sum = 0; if (item.Value != null && item.Value.Count > 0) { foreach (var temp in item.Value) { sum += temp; } } // this.subSumList.Add(sum);
lock (lockObj)
{
this.resultList.Add(index, sum);
}
} end = DateTime.Now; Console.WriteLine("线程" + index + "执行完毕,耗时" + ((TimeSpan)(end - start)).TotalMilliseconds); this.autoEvents[index].Set(); } /// <summary> /// 重置手动事件为终止状态 /// </summary> /// <param name="obj">obj</param> private void SetManualEvent(object obj) { ////重置手动事件为终止状态 this.manualEvent.Set(); } } }
2、测试
public static void Test2() { List<int> list = new List<int>(); for (int i = 0; i < 1000000; i++) { list.Add(i); } DateTime start = DateTime.Now; DateTime end = DateTime.Now; long sum = 0; for (int i = 0; i < list.Count; i++) { sum += list[i]; } end = DateTime.Now; Console.WriteLine("主线程结果:" + sum + ",耗时:" + ((TimeSpan)(end - start)).TotalMilliseconds); start = DateTime.Now; SumMultiThread2 thread = new SumMultiThread2(list, 10); thread.Execute(); end = DateTime.Now; Console.WriteLine("多线程结果是:" + thread.Result + ",耗时:" + ((TimeSpan)(end - start)).TotalMilliseconds); Console.Read(); }
3、注意数据分配
注意list 本身是线程不安全的,要加锁才能达到目的。谢谢 楼下的 一叶知秋 帮忙发现的问题。