请教一个多线程设计的问题

ayun00 2017-06-27 11:37:13
我有一个list<object>, 这个list 的元素会动态的增加,删除

然后每个object对象 有一个专属的 queue 队列, 这个里面的数据必须被顺序处理

怎么用多线程来处理所有的 queue?

简单的
while(true)
{
foreach(var item in list)
{
task.run(()=>{......});
}
}
感觉有2点
1.循环list 的开销有点大
2. 有可能不同的task会执行同一个queue , 造成 queue 中的数据不能被顺序处理
...全文
282 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuzuning 2017-06-27
  • 打赏
  • 举报
回复
你先把事情搞清楚了再说,不要自己绕自己 既然是 每个object对象 有一个专属的 queue 队列, 这个里面的数据必须被顺序处理 那么对象本身的内部处理是不能交由多线程完成的 所以并不需要知道对象是什么,都做了什么 你只需用 Parallel.For 去循环 list<object> 就可以了 有可能不同的task会执行同一个queue每个object对象 有一个专属的 queue 队列 相矛盾!
闭包客 2017-06-27
  • 打赏
  • 举报
回复
加一个同步锁就可以了,不过这样损失了多线程的意义。你可以考虑在对象处理完成之后再排序,如果每个对象的处理都依赖于上一个处理的结果,那么你这个业务逻辑是无法做成多线程的。
ayun00 2017-06-27
  • 打赏
  • 举报
回复
list 对象 可能会有上万个
ayun00 2017-06-27
  • 打赏
  • 举报
回复
引用 1 楼 xdashewan 的回复:
1.开销大的根据是什么,list总量? 2.不应该存在这种情况 你这种情况其实就是处理list<queue>,如果需要同时处理queue,那么必要启动多个task或thread,如果可以一个一个处理list中queue,那你连list都没有存在必要,直接所有元素全部放queue足以
list中的object 不是 queue , 现在是每个object 在队列服务器中有一个队列对象
xdashewan 2017-06-27
  • 打赏
  • 举报
回复
1.开销大的根据是什么,list总量? 2.不应该存在这种情况 你这种情况其实就是处理list<queue>,如果需要同时处理queue,那么必要启动多个task或thread,如果可以一个一个处理list中queue,那你连list都没有存在必要,直接所有元素全部放queue足以
正怒月神 2017-06-27
  • 打赏
  • 举报
回复
听起来是要找一个线程安全的集合?》 http://blog.csdn.net/wlanye/article/details/8668089
GT7466 2017-06-27
  • 打赏
  • 举报
回复
网上随便找了个例子:http://www.cnblogs.com/yukaizhao/archive/2009/12/16/system_threading_threadpool_AsyncHelper_1.html 外层循环条件是你的线程数量,你要用task处理也一样,如你可以人为将10000个item分为50段,每段200,每个task处理一段。
GT7466 2017-06-27
  • 打赏
  • 举报
回复
“list对象 可能会有上万个” 其实你的核心需求是处理上万个长任务,自己把问题描述复杂了。 list 有上万个,当然不能在循环里开1万个线程, 但你可以分段啊,假设你打算开100个线程,那每个线程处理10000/100 个item不就可以了,连内部锁控制都不用。
bloodish 2017-06-27
  • 打赏
  • 举报
回复
下面这一段是介绍: BlockingCollection<T> is a thread-safe collection class that provides the following: An implementation of the producer/consumer pattern; BlockingCollection<T> is a wrapper for the IProducerConsumerCollection<T> interface. Concurrent addition and removal of items from multiple threads with the Add and Take methods. A bounded collection that blocks Add and Take operations when the collection is full or empty. Cancellation of Add or Take operations by using a CancellationToken object in the TryAdd or TryTake method. 这一段是说明BlockingCollection的实现不仅支持队列方式的访问(FIFO),也支持堆栈方式(LIFO),默认行为是FIFO When you create a BlockingCollection<T> object, you can specify not only the bounded capacity but also the type of collection to use. For example, you could specify a ConcurrentQueue<T> object for first in, first out (FIFO) behavior, or a ConcurrentStack<T> object for last in, first out (LIFO) behavior. You can use any collection class that implements the IProducerConsumerCollection<T> interface. The default collection type for BlockingCollection<T> is ConcurrentQueue<T>.
bloodish 2017-06-27
  • 打赏
  • 举报
回复
命名空间System.Collections.Concurrent下,增加了很多支持并发操作的集合类型. 根本不需要你考虑锁的问题.之前提到的BlockingCollection是用于支持生产者-消费者模型的一种实现.而你需求就符合一模型. BlockingCollection内部就是用了队列,这一点你可以查MSDN或者通过Reflector等工具反编译代码自行查看.
ayun00 2017-06-27
  • 打赏
  • 举报
回复
引用 5 楼 xuzuning 的回复:
你先把事情搞清楚了再说,不要自己绕自己 既然是 每个object对象 有一个专属的 queue 队列, 这个里面的数据必须被顺序处理 那么对象本身的内部处理是不能交由多线程完成的 所以并不需要知道对象是什么,都做了什么 你只需用 Parallel.For 去循环 list<object> 就可以了 有可能不同的task会执行同一个queue每个object对象 有一个专属的 queue 队列 相矛盾!
@GT7466 说的比较清楚
ayun00 2017-06-27
  • 打赏
  • 举报
回复
引用 8 楼 GT7466 的回复:
我复述下: 你list里的item是希望多线程并发的,但item内queue里面的数据必须被顺序处理,即你希望工作线程是“均匀分布”在list.>item这个层面,同时担心2个线程连续命中同一个item,并先后领取了该item内queue连续2个出列--这个情景隐藏着queue被乱序处理的危险。 鉴于你可能很难判断出列的任务是否已经及时处理完,并以此放出下一个任务,所以控制处理放在item这里比较好。 具体的,item内的对象是独立的,你不能在object内进行静态的同步锁判断,而应该锁具体的item, 某线程处理某item时,锁定该item,并领取一个出列任务,后续的线程在此期间都无法进入该item,保证了queue的顺序处理,处理完解开此item。
对 你的描述大部分是对的, 有一点不同的是 queue不是item 的一部分, 是外部的, item有一个key ,根据这个key 维护一queue对象, 我后来又想了 双 queue方式, 但是还没有理清楚, 你说的这种加lock的方式 , 应该也是一种方案, 不过还是没有解决要循环list 的问题
GT7466 2017-06-27
  • 打赏
  • 举报
回复
我复述下: 你list里的item是希望多线程并发的,但item内queue里面的数据必须被顺序处理,即你希望工作线程是“均匀分布”在list.>item这个层面,同时担心2个线程连续命中同一个item,并先后领取了该item内queue连续2个出列--这个情景隐藏着queue被乱序处理的危险。 鉴于你可能很难判断出列的任务是否已经及时处理完,并以此放出下一个任务,所以控制处理放在item这里比较好。 具体的,item内的对象是独立的,你不能在object内进行静态的同步锁判断,而应该锁具体的item, 某线程处理某item时,锁定该item,并领取一个出列任务,后续的线程在此期间都无法进入该item,保证了queue的顺序处理,处理完解开此item。
bloodish 2017-06-27
  • 打赏
  • 举报
回复
引用 6 楼 bloodish 的回复:
可以使用并发队列:BlockingCollection 具体可以查MSDN 也可以参考我在这个帖子里的回帖
回帖地址 blocking collection
bloodish 2017-06-27
  • 打赏
  • 举报
回复
可以使用并发队列:BlockingCollection 具体可以查MSDN 也可以参考我在这个帖子里的回帖

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧