高级问题!怎样多线程操作队列?

问题描述

比如,有一个数据表(可以理解为队列不?)中有5000条未完成数据,每条数据需要进行复杂的计算、处理、写入文本文件后才能标记为完成。现在是单台机器按先进先出的原则逐条处理。领导觉得太慢了,想加几台机器同时处理【数据表是同一个】。我现在想法是,假如有两台机器,每台机器每五分钟读取一些待处理数据,然后处理。A机器处理ID为单号的,B机器处理ID为双号的。大家觉得可行吗?MSsql不能select单双数ID吧。。。我知道这是一个很笨的方法,期待高手们能有更好的方法

解决方案

解决方案二:
所谓的多线程就是开启多个线程同时执行某个单项任务,最终完成某个事情的过程。但是并不是开启的线程数越多越好,到达一个临界点之后,效率反而会降低。你首先要做的就是将你的任务进行分解(比如你有5000条数据,开启5个线程,线程1处理1-1000条数据,线程2处理1001-2000条数据,以此类推),然后让线程单独执行各自的操作,最后共同完成这项任务。
解决方案三:
首先,假设要处理5000个并发任务,可以使用这样的写法。例如我们准备一个“测试条件”集合,随便用顺序号来表示varcondition=Enumerable.Range(0,5000).ToList();

假设每当接受一个输入编号,进行一项计算,这样模拟staticRandomrnd=newRandom();privatestaticboolsolve(intx){returnrnd.Next(2)+x==0;}

那么要并发执行这5000千个solve方法(输入的x各不相同),则应该这样写varresult=(fromxincondition.AsParallel()selectsolve(x)).ToList();

这就是并发执行这些任务。对于你的程序来说,如果在一台机器上并发处理这5000条记录,那么就可以用condition来一次读取出来5000条数据,用solve来处理记录(单个记录对应的实体对象代替这里的x变量),最后得到每条记录处理的结果集合,返回统计。对于plinq来说,它使用了.net的系统线程池,因此可以根据你的机器的使用情况来自动优化并发数量。所以不用担心、也不用手动规定什么并发数据量。当然如果你想限制最多用30个并发线程,也可以手动规定,例如varresult=(fromxincondition.AsParallel().WithDegreeOfParallelism(30)selectsolve(x)).ToList();

但是通常不必这样多此一举。
解决方案四:
对于你分布式处理问题,由于比较简单,我们用基本的分布式原则(而且不考虑内外网之分)来设计,不用纠结什么高大上的什么开源框架(.net中也没有类似PLinq那样的现成的框架)。那么可以这样设计:你可以为你的数据库表加上一个“状态”字段,至少有三种状态值:1.未处理。2.正在处理。3.处理完毕。然后假设你有n台机器(千万比要想当然地以为固定为5台机器或者2台机器,不然反而造成资源浪费),每台机器都访问这个数据库来“抢夺”一个处于“未处理”状态的记录、并且在同一个事务中把它变为“正在处理”状态。这个操作肯定很快,连查询带改变状态(在同一个事务中)然后读取记录,这三项功能也就几毫秒就做完了。然后就对记录进行你的费时的处理,然后把处理结果送到统一规定的位置,然后处理下一条数据。这跟你的“A、B”机的说法类似,区别是,这里不假设只能有2台机器。并且注意数据库操作尽可能限制在4、5毫秒之内。而且也不是什么“每隔5分钟处理一批数据”。应该是收到请求既启动。例如其发布的网页只要被人访问一下,例如http://192.268.1.203:81/proc1/default.ashx就触发其启动。这样,当年任何地方知道有数据产生的时候,改变这里的ip来通知各个机器(机器的ip地址可以配置好)开始启动操作就行了。根据机器的处理速度的快慢、以及数据本身的不同,可能A机器处理了2100条记录,B机器处理了1850条记录,C机器处理了1050条记录,这都是可能的。不要想当然地以为需要固定指定“几台机器,每台机器分别处理哪些条记录”。看似简单但是死板的设计会产生很差的性能。
解决方案五:
引用2楼sp1234的回复:

首先,假设要处理5000个并发任务,可以使用这样的写法。例如我们准备一个“测试条件”集合,随便用顺序号来表示varcondition=Enumerable.Range(0,5000).ToList();

假设每当接受一个输入编号,进行一项计算,这样模拟staticRandomrnd=newRandom();privatestaticboolsolve(intx){returnrnd.Next(2)+x==0;}

那么要并发执行这5000千个solve方法(输入的x各不相同),则应该这样写varresult=(fromxincondition.AsParallel()selectsolve(x)).ToList();

这就是并发执行这些任务。对于你的程序来说,如果在一台机器上并发处理这5000条记录,那么就可以用condition来一次读取出来5000条数据,用solve来处理记录(单个记录对应的实体对象代替这里的x变量),最后得到每条记录处理的结果集合,返回统计。对于plinq来说,它使用了.net的系统线程池,因此可以根据你的机器的使用情况来自动优化并发数量。所以不用担心、也不用手动规定什么并发数据量。当然如果你想限制最多用30个并发线程,也可以手动规定,例如varresult=(fromxincondition.AsParallel().WithDegreeOfParallelism(30)selectsolve(x)).ToList();

但是通常不必这样多此一举。

大神可能没有明白简单的说,我现在有一个队列表,其中是有很多条任务,任务队列不断的增加,程序定期访问这个表,得到未处理的任务进行处理,然后处理完成做标记。如果现在有两台服务器,我可以一台处理单数ID,另一台处理偶数ID的任务。我希望能有更好的方法
解决方案六:
关键的问题在于,数据在公网,而工作的几台机器在内网。这样就没有办法通知它们起来工作,除了让它们定时来轮询
解决方案七:
实际上,所谓分布式计算,非常简单。上面的很简单模型已经有了完整的框架雏形,只不过实现方法不同而已。1.首先需要有一个client负责将任务倒入到系统中,然后通知一个master机器处理这一批次的任务。2.然后master通知所有的worker机器这个批次中的每一个任务。3.worker采取“抢任务”的方式,这样即使是你在任务处理前1分钟才临时增加10台服务器或者减少5台服务器,系统也自动根据各个服务器的负载情况而自动地调配。因为反应比较慢的烂机器,就没有人家好机器“抢”的多。只不过大型的分布式系统通常用master机的内存状态来协调,而不是像上面那样用数据库记录来协调,只是存储上的区别。4.workder处理完毕之后,根据任务代码编写的业务逻辑,把结果推送到某个地方。例如你的worker可以每当推送结果给某个固定存储地址后,就像client一样去让master机器启动一个reduce任务来合并任务(可以给出积攒了多少内容之后才真正开始合并)。甚至启动一个notifypush任务去向前端设备发送一个“请来读取结果”的通知。分布式处理,是任何一个软件服务公司都最基本的应该掌握的编程知识。不习惯于做这个,跟10几年的走街串巷卖进销存软件的小公司也就差不多了,也就慢慢跟不上最近这几年的时代的步伐了。
解决方案八:
引用5楼ranranshengqi的回复:

关键的问题在于,数据在公网,而工作的几台机器在内网。这样就没有办法通知它们起来工作,除了让它们定时来轮询

如果不在同一个局域网,那么就使用长连接,服务器给客户端推送消息啊。
解决方案九:
你可以看看一个服务器在公网,然后许多客户端在(各自的)局域网内,如何保持双向长连接操作。我在之前贴过一个简单的tcp长连接的底层代码的例子。
解决方案十:
谢谢楼上的高手,受教了!
解决方案十一:
多台机器同时处理数据,防冲突就是加一个状态,谁加了这个状态就由谁处理

时间: 2024-09-23 06:52:47

高级问题!怎样多线程操作队列?的相关文章

请教多线程操作同一个数据表时,怎么避免表死锁

问题描述 最近有一个数据采集的项目,要求可以多路并发,遇到多线程操作同一个数据表的问题,经常发生表死锁,求各位大侠帮忙,大约有20-40个进程实例化读取类,类中Receive方法接收数据并存储上代码publicclassclsTranslateObj{privatevoidReceive(){intlenReceive=0;byte[]receivedByte=newbyte[BUFFER_SIZE];//接收返回字节数组_rtnStr=string.Empty;while(_flgConnec

Python多线程和队列操作实例

  这篇文章主要介绍了Python多线程和队列操作实例,本文直接给给实例代码,需要的朋友可以参考下 Python3,开一个线程,间隔1秒把一个递增的数字写入队列,再开一个线程,从队列中取出数字并打印到终端 代码如下: #! /usr/bin/env python3 import time import threading import queue # 一个线程,间隔一定的时间,把一个递增的数字写入队列 # 生产者 class Producer(threading.Thread): def __i

PHP 高级编程之多线程(四)-多线程与ZeroMQ

PHP 高级编程之多线程 http://netkiller.github.io/journal/thread.php.html Mr. Neo Chen (netkiller), 陈景峰(BG7NYT)     中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 +86 755 29812080<netkiller@msn.com> 版权 2011, 2012, 2013, 2014 http://netkiller.github.io 版权声明 转载请与作

PHP 高级编程之多线程(第三版)

PHP 高级编程之多线程 http://netkiller.github.io/journal/thread.php.html Mr. Neo Chen (netkiller), 陈景峰(BG7NYT)     中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 +86 755 29812080<netkiller@msn.com> 版权 2011, 2012, 2013, 2014 http://netkiller.github.io 版权声明 转载请与作

PHP 高级编程之多线程(二)

PHP 高级编程之多线程 http://netkiller.github.io/journal/thread.php.html Mr. Neo Chen (netkiller), 陈景峰(BG7NYT) 中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 +86 755 29812080<netkiller@msn.com> 版权 2011, 2012, 2013, 2014 http://netkiller.github.io 版权声明 转载请与作者联系,

PHP 高级编程之多线程

PHP 高级编程之多线程 http://netkiller.github.io/journal/thread.php.html Mr. Neo Chen (netkiller), 陈景峰(BG7NYT) 中国广东省深圳市龙华新区民治街道溪山美地518131+86 13113668890+86 755 29812080<netkiller@msn.com> 版权 2011, 2012, 2013, 2014 http://netkiller.github.io 版权声明 转载请与作者联系,转载时

javascript 多线程异步队列

首先,你得知道 jQuery.Deferred 的大致用法,然后,我们进入正题吧: 库代码: /*!  * 多线程异步队列  * 依赖 jQuery 1.8+ (如果你用的是 1.6或1.7, 只要将源码中的 then方法替换为pipe方法 即可)  */ /**  * @n {Number} 正整数, 线程数量  */ function Queue (n) {     n = parseInt(n 1, 10);     return new Queue.prototype.init( (n

如何在Weblogic的全局事务执行多线程操作

今天有人提出了一个诡异的要求,要求在全局事务中执行多线程操作.他们 全局事务中涉及两个数据库中的多个表,如果单线程那么走完,相应时间上不满 足要求,说白了就是比较慢,于是提出了这样的要求.从JTA的规范来看, transaction(TX)和thread是密切相关的,TX一般是不能在应用线程间传递的, 即我主线程起一个全局事务,然后我把这个事务传递给其他我新起的线程,单纯 的变量传递没问题,但这个事务是不能被transaction manager(TM)识别的,TM 对TX的管理有他自己的方式.

PHP CURL 多线程操作代码实例

  这篇文章主要介绍了PHP CURL 多线程操作代码实例,本文直接给出实现代码,需要的朋友可以参考下 使用方法: ? 1 2 3 $urls = array("http://baidu.com", "http://21andy.com", "http://google.com"); $mp = new MultiHttpRequest($urls); $mp->start(); ? 1 2 3 4 5 6 7 8 9 10 11 12 1