2014-09-25 23 views
1

我有某些对象需要执行某些任务。所有对象都需要执行所有任务。我想要使​​用多个线程说N个并行线程在多个键上进行散列:用于执行任务在多线程环境中

说我有对象标识符像A,B,C(对象可以在100 K范围内;键可以是长或字符串) 和任务可以T1,T2,T3 ,TN - (任务数量最大为20)

执行任务的条件 - 即使对于同一个对象,也可以并行执行任务。 但是对于同一个对象,对于一个给定的任务,它应该被串行执行。 实施例,说我有在其上的任务执行是A,B,A 和任务是T1,T2 对象

所以T1(A),T2(A)或T1(A),T2(B)是可能的,但不应允许T1(A)和T1(A)

如何确保满足我的条件。我知道我必须使用某种哈希。 我读到散列,所以我的散列函数可以是 -

返回ObjectIdentifier.getHashCode()+ TaskIdentifier.getHashCode() 或其它可以是 - 一个^ 3 + B^2(其中,a和b是散列对象标识符和任务标识符分别) 什么是最佳策略,任何建议

我的任务不涉及任何IO,并且截至目前,我正在为每个任务使用一个线程。 所以我目前的设计是好的,或者我应该尝试根据处理器的数量来优化它。 (有固定的线程NUM)

+0

感谢您的回答,您好,我的ListOfObjects是我从外部程序recv(通过阻止收集)的一系列消息。在完成n条消息或接收条件之后,我必须停止处理消息,处理该条件,然后继续处理(继续执行阻塞收集循环)。我无法理解如何使用阻止收集来的消息来实现上述功能 – 2014-09-26 00:47:09

回答

1

您可以在列表中的一个做Parallel.ForEach,和其他列表定期的foreach,例如:

Parallel.ForEach (myListOfObjects, currentObject => 
{ 
    foreach(var task in myListOfTasks) 
    { 
     task.DoSomething(currentObject); 
    } 
}); 
1

我必须说,我真的很喜欢鲁弗斯L的回答。你必须聪明地对待你平行的事情,而不是过度地使用过多的线程同步和内存密集型构造来阻碍你的实现 - 这些东西减少了并行化的好处。考虑到项目池的大尺寸和工作的CPU约束性质,带有顺序内部循环的Parallel.ForEach应该提供非常合理的性能,同时保持实现简单。这是一场胜利。

说了这么多,我有一个很平凡的基于LINQ的好办法来Rufus的答案,满足您的其他要求(这是对同一个对象,对于一个给定的任务,它应该在一系列执行) 。解决方案的工作条件是以下假设成立:

  • 执行任务的顺序并不重要。
  • 要进行的工作(任务 x 对象的所有组合)事先已知并且不能更改。
  • (对不起,指出显而易见)您想并行的工作可以平行 - 即没有共享资源/副作用是完全隔离的。

考虑到这些假设,考虑以下因素:

// Cartesian product of the two sets (*objects* and *tasks*). 
var workItems = objects.SelectMany(
    o => tasks.Select(t => new { Object = o, Task = t }) 
); 

// Group *work items* and materialise *work item groups*. 
var workItemGroups = workItems 
    .GroupBy(i => i, (key, items) => items.ToArray()) 
    .ToArray(); 

Parallel.ForEach(workItemGroups, workItemGroup => 
{ 
    // Execute non-unique *task* x *object* 
    // combinations sequentially. 
    foreach (var workItem in workItemGroup) 
    { 
     workItem.Task.Execute(workItem.Object); 
    } 
}); 

请注意,我不是限制Parallel.ForEach并行度。由于所有工作都是CPU限制的,因此它会自行计算出最佳线程数。