我有个问题,不知是否正确,请各位指点:假如一条消息(单线程中)发送完毕需要10秒,我现在有10个这样的消息,
如果按照单线程的做法,依次发送,大约要10*10=100多秒吧。
现在我就为这10个消息各创建一个线程,我认为等待所有线程结束(发送完毕)
所需的时间也是10*10=100多秒,因为你是单CPU, CPU时间片是20ms,线程间只不过是
时间片的轮用,并不是同时执行!
如果按照单线程的做法,依次发送,大约要10*10=100多秒吧。
现在我就为这10个消息各创建一个线程,我认为等待所有线程结束(发送完毕)
所需的时间也是10*10=100多秒,因为你是单CPU, CPU时间片是20ms,线程间只不过是
时间片的轮用,并不是同时执行!
能不能给点代码,我对(互斥,事件,信号量)不是很熟.
不能出现多个线程读到相同数据的情况吗?
如果并发执行的时候,操作系统发现一个线程处于等待阻塞,会切换到另外一个线程去做,这样可以充分利用CPU。比如:
1,1-10个线程分别用了0.5秒初始化,总共:0.5*10=5妙
2, 1-10个线程都进入阻塞,分别用了9秒,由于并发等待,只用9秒
3,1-10个线程分别用了0.5秒处理结果,总共:0.5*10=5妙
总共是:5+9+5=19秒,而不是5+9*10+5=100秒,是不是提高了效率?硬盘的DMA也是类似的原理,为什么有了DMA后,速度没有提高,效率会提高?因为操作系统不需要傻等,可以在等待的时间做其它事情!总之,多线程的好处在于通过类似运筹的方法,可以充分利用资源(包括CPU,IO,网络)。如果只利用CPU一种资源,用多线程是绝对不能提高速度的(比如做一个矩阵运算,只用CPU资源,开多线程还不如用一个线程做快呢!)
确实,如果在执行一个纯粹的复杂计算(如三维图象处理),只利用CPU一种资源,此时用多线程绝对不能提高速度!
那么对于另一种内部存在"等待阻塞"的线程,究竟他在什么情况下会阻塞而不占用CPU资源呢?Sleep会吗? WaitForSingleObject会吗?阻塞socket的recv会吗?
可能都不到1s。这才是要优化的地方,多线程没有什么意义。
to vcbear(一只平凡无知的熊)
我刚试过,虽然数据库的负载小了,可效果不明显。
实际上时间都浪费在发送数据上了。最好的方式就是向下面这种情况,我不知道如何实现。
在每个线程中都有打开数据库的操作。如select top 10 from ms_unsend
当第一个线程执行时取到表中的前十个记录,进行发送,计费,删除当前记录的操作。
而第二个线程执行select top 10 from ms_unsend时相当与从记录的第十一个读取。如总共表中的数据不足10个,即被前者读走(锁定)。那么则此线程退出。
发送过程有没有应答等待,如果有,恭喜,可以用多线程方式优化流程。
线程读数据库的过程可以进行同步,这样不如专门开一个线程读数据库,不断的把数据加入缓冲。
因为读数据库的过程中,sql语句是在服务器端执行的,这个期间客户线程只是等待而已,多线程
方式可以充分利用cpu时间。
这样的话只需要两种线程
1:读数据库的线程,一个应该就够了,一次读个1000个数据,放到程序的缓冲里(考虑用链表或CArray)
2:发送短消息的线程,从缓冲里读数据,看情况了,如果发送动作效率很高,就不要用多个了效果要试过才知道
现在是在解决20-30条数据发送的时间问题,大约需要54个小时,太久了
偶是新手,关注!
看你的实际情况,你的bottle neck 是在发送短消息这一块。你可以用一个线程专门负责发送短消息,通常情况下是足够的,因为GSM短消息是通过No.7信令网发送的,而No.7信令网的带宽是64K,用一个线程处理就足够了。
剩下的问题就在于短消息的生成,这时可以使用多线程,每个线程负责从数据库读取数据,生成短消息,再将生成的短消息都放到发送短消息的线程的短消息队列中去。当发送线程的短消息队列满的时候,生成短消息的线程可暂停工作,这时要考虑到线程之间的同步问题。注意,这些线程可以以进程池的形式存在,不需要经常创建,结束,这样系统开销太大,与数据库的连接也如此。
要争取的时间。线程数多于连接数没有意义,因为这样对于一个连接也还是线程同步导致的
排队等待IO的事情。