我有个问题,不知是否正确,请各位指点:假如一条消息(单线程中)发送完毕需要10秒,我现在有10个这样的消息,
如果按照单线程的做法,依次发送,大约要10*10=100多秒吧。
现在我就为这10个消息各创建一个线程,我认为等待所有线程结束(发送完毕)
所需的时间也是10*10=100多秒,因为你是单CPU, CPU时间片是20ms,线程间只不过是
时间片的轮用,并不是同时执行!

解决方案 »

  1.   

    to gongxy:
    能不能给点代码,我对(互斥,事件,信号量)不是很熟.
    不能出现多个线程读到相同数据的情况吗?
      

  2.   

    to WhiteWaterBlueSky(疯狂数码):不是这样的,如果有10个线程,比如1-10。每个单独做确实要10秒,但是其中9秒是等待网络阻塞返回的时间,这段时间并不消耗CPU资源。也就是说每个线程只消耗1秒的CPU资源。
    如果并发执行的时候,操作系统发现一个线程处于等待阻塞,会切换到另外一个线程去做,这样可以充分利用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资源,开多线程还不如用一个线程做快呢!)
      

  3.   

    谢谢plato(天天)!
    确实,如果在执行一个纯粹的复杂计算(如三维图象处理),只利用CPU一种资源,此时用多线程绝对不能提高速度!
    那么对于另一种内部存在"等待阻塞"的线程,究竟他在什么情况下会阻塞而不占用CPU资源呢?Sleep会吗? WaitForSingleObject会吗?阻塞socket的recv会吗?
      

  4.   

    减少数据库访问次数,数据库访问开销是很大的,比如一次读1个数据是10ms,但是读1000个数据
    可能都不到1s。这才是要优化的地方,多线程没有什么意义。
      

  5.   

    不是不给分,是上面的方法行不通。
    to vcbear(一只平凡无知的熊) 
    我刚试过,虽然数据库的负载小了,可效果不明显。
    实际上时间都浪费在发送数据上了。最好的方式就是向下面这种情况,我不知道如何实现。
    在每个线程中都有打开数据库的操作。如select top 10 from ms_unsend
    当第一个线程执行时取到表中的前十个记录,进行发送,计费,删除当前记录的操作。
    而第二个线程执行select top 10 from ms_unsend时相当与从记录的第十一个读取。如总共表中的数据不足10个,即被前者读走(锁定)。那么则此线程退出。
      

  6.   

    最近我也在写这个程序,不过我用Delphi + SQl Server + Wave Com我用delphi,可以一起探讨。[email protected]
      

  7.   

    首先你要计算一下,根据你的GSM Modem(或者其他东西),发送一条短消息需要多长时间,
    发送过程有没有应答等待,如果有,恭喜,可以用多线程方式优化流程。
    线程读数据库的过程可以进行同步,这样不如专门开一个线程读数据库,不断的把数据加入缓冲。
    因为读数据库的过程中,sql语句是在服务器端执行的,这个期间客户线程只是等待而已,多线程
    方式可以充分利用cpu时间。
    这样的话只需要两种线程
    1:读数据库的线程,一个应该就够了,一次读个1000个数据,放到程序的缓冲里(考虑用链表或CArray)
    2:发送短消息的线程,从缓冲里读数据,看情况了,如果发送动作效率很高,就不要用多个了效果要试过才知道
      

  8.   

    我是用vc + SQL Server.
    现在是在解决20-30条数据发送的时间问题,大约需要54个小时,太久了
      

  9.   

    WhiteWaterBlueSky(疯狂数码)和plato(天天)的讨论很有启发!
    偶是新手,关注!
      

  10.   

    回答WhiteWaterBlueSky(疯狂数码):>Sleep会吗? WaitForSingleObject会吗?阻塞socket的recv会吗?都不会占用CPU,也就是说系统会让其他需要CPU的线程运行。
      

  11.   


    看你的实际情况,你的bottle neck 是在发送短消息这一块。你可以用一个线程专门负责发送短消息,通常情况下是足够的,因为GSM短消息是通过No.7信令网发送的,而No.7信令网的带宽是64K,用一个线程处理就足够了。
    剩下的问题就在于短消息的生成,这时可以使用多线程,每个线程负责从数据库读取数据,生成短消息,再将生成的短消息都放到发送短消息的线程的短消息队列中去。当发送线程的短消息队列满的时候,生成短消息的线程可暂停工作,这时要考虑到线程之间的同步问题。注意,这些线程可以以进程池的形式存在,不需要经常创建,结束,这样系统开销太大,与数据库的连接也如此。
      

  12.   

    保持一个连接一个线程即可,IO过程总是会有一些Block或者Overlapp时间的,这段时间就是
    要争取的时间。线程数多于连接数没有意义,因为这样对于一个连接也还是线程同步导致的
    排队等待IO的事情。