标题党,哈哈,帮我看看下面模型怎么优化下吧,总感觉比较乱。
    说明:数据库连接因为其他问题,只能放在线程函数中。    UINT ReadResource(LPVOID pParam)
{
InterlockedIncrement(&g_nReadThreadNum);
sReadThreadInit* pRdInit = (sReadThreadInit*)pParam;
CANNaviReadResource cReadResource;
        初始化成员变量
BOOL bRet = cReadResource.OpenConnect(); //连接数据库
从全局队列中取数据(两个队列A,B,A中没数据才从B中取
while(bRet)
{
如果两个队列都没数据,线程挂起,并把线程状态设置未挂起 判断退出标志
if(A队列有数据)
{
执行对应函数 if(g_bEndThreadAll || g_nWriteThreadNum == 0) //判断用户发出退出请求或者写线程退出
{
if(当前只要自己处于工作状态)
                                {
                                     将所有读线程的状态设置为退出;
                                     激活所有线程;
                                }
break;
}
}
else
{

    if(当前只要自己处于工作状态)
                     {
                           将所有读线程的状态设置为退出;
                             激活所有线程;
                      }
break;

}
从全局队列中取数据(两个队列A,B,A中没数据才从B中取

}
delete pRdInit;
InterlockedDecrement(&g_nReadThreadNum);
return 0;
}

解决方案 »

  1.   

    重新排下版 UINT   ReadResource(LPVOID   pParam) 

    InterlockedIncrement(&g_nReadThreadNum); 
    sReadThreadInit*   pRdInit   =   (sReadThreadInit*)pParam; 
    CANNaviReadResource   cReadResource; 
            初始化成员变量 
    BOOL   bRet   =   cReadResource.OpenConnect();   //连接数据库 
    从全局队列中取数据(两个队列A,B,A中没数据才从B中取 
    while(bRet) 

    如果两个队列都没数据,线程挂起,并把线程状态设置未挂起  判断退出标志  if(A队列有数据) 

    执行对应函数  if(g_bEndThreadAll   ||   g_nWriteThreadNum   ==   0)   //判断用户发出退出请求或者写线程退出 

    if(当前只要自己处于工作状态) 
                                    { 
                                            将所有读线程的状态设置为退出; 
                                            激活所有线程; 
                                    } 
    break; 


    else 
    {          if(当前只要自己处于工作状态) 
                             { 
                                 将所有读线程的状态设置为退出; 
                                  激活所有线程; 
                             } 
    break;  }  从全局队列中取数据(两个队列A,B,A中没数据才从B中取  } 
    delete   pRdInit; 
    InterlockedDecrement(&g_nReadThreadNum); 
    return   0; 
    }
      

  2.   

    你的性能可能在这里有问题
    CANNaviReadResource cReadResource;  初始化成员变量 
    BOOL bRet = cReadResource.OpenConnect(); //连接数据库  
    如果成员比较到,则要不停的初始化和析构
    还有连接数据库
    你最好设置全局变量,这样的效率会提高很多
      

  3.   

    你这里并没有清楚描述得到你的线程模型, 只是看起来, 你存在两个队列, 大概是有两个线程会写入.
    然后这段函数, 大概是并行读取出来进行处理的函数. 就这段描述来说, 你采用的方式, 是有问题的, 上网查找一下MS-Queue的流程. 我想会对你有帮助.
      

  4.   

    两个队列并不是由两个线程写入的。其中队列B数据是在创建线程时传入的。队列A的数据,是处理函数根据一定情况写入得。
    对于你说的‘MS-Queue的流程’,我搜索到,多数是服务器之间通信的,线程之间也可以用吗?
      

  5.   

    你搜索错了, 你搜到的是微软的...你搜索  无锁队列  吧..这个是线程间, 不能够跨进程. 用于实现多写多读并行无锁, 比较适合你现有的方式, 但这队列效率不算高, 但由于有代码可以抄..所以很方便.假如你的只是一写一读的模型, 网上也有很多可以抄, 假如是一写多读的模型, 还是改用MS-Queue最简单了. 在线程运转速度不算太高的情况下, MS-Queue的效率还是可以的.
      

  6.   

    这个跟无锁队列的应用不冲突吧...网上的代码都是无阻塞形式, 也没有休息的形式的, 实际应用中除非真的对效率要求非常高, 有很多个CPU死循环检测并读取列表数据, 一边都要自己加上Event来让读线程在没有数据可以读的时候挂起, 不过也个也是难点之一.
      

  7.   


    从两个队列中读取数据, 有多少个读线程呢? 这个队列除了被读以外, 难道不用被写就会自动有数据了? 
    先不管这里你有多少个写, 起码这两个队列均会被多个读线程访问得到, 那么其模型是要求 并行读(多读).
    然后读线程要从数据库得出数据, 放入共享区, 这个共享区的模型是要求 并行写(多写)
    写线程从共享区读取数据, 然后写入另外一个数据库, 这个模型是要求 单读单写并行, (一读一写)你对何为读线程, 何为写线程, 是从你的业务角度去考虑的, 然后认为这个线程做读取数据库的就叫读线程, 这个线程写数据库的就叫写线程. 这些对于线程模型来说, 不应该采用这种方式来理解的.采用MS_Queue, 你的两个被读取队列可以直接综合成一个, 反正是FIFO的, 你的"读线程"可以随便有很多个, 并行直接读取这个Queue即可, 你的共享区, 用MS_Queue之后, 可以随便被"读线程"写入共享数据, "写线程"就可以直接从共享区(即MS_Queue)里面FIFO的形式把数据读取出来, 放入另一个数据库. 有一点很奇怪的是, 为何你非得要用两个队列来让读取线程读呢? 搞优先级别吗?
      

  8.   

    是的,有优先级的。
    数据产生:创建线程之前,队列A为空,队列B中放入数据.两个队列的数据不一样的。队列A未ID范围(最大-最小值),队列B为包ID(一个包下面有很多记录ID)
    读线程:从队列A取,没有取到。从队列B中取。然后从数据库中取出记录。如果记录很多,将记录很多,把数据重新分包(其实就是简单记录ID范围),放回队列A中。退出。对于读写线程定义,我是以数据库来区分的。从数据库中读取数据,称之为读线程。反之,为写线程。
      

  9.   

    只要你简单转变一下思维, 把线程的读还是写跟业务区分开来, 就可以很清楚你的业务数据流向了.用上线程安全的FIFO队列(用无锁效率高点, 临界区效率低点, 但不影响数据流动), 这样就可以直接按照你的描述来做事了. 
    首先建立N个"读线程", 并行读取A, 假如A有数据, 那么处理完成后放入"共享区", 直到A读取完成为止. 然后转入B列表的读取, 假如B有数据, 则查询数据库, 生成N条数据写入A列表. 这个过程被N个"读线程"并行进行, 最终输出到"共享区", 由"写线程"读取"共享区", 写入另外一个数据库. 也就是这样一个流程.不过我建议你还是简化一下, 建立一个线程是专门读取列表B数据的, 建立一个线程专门读取A数据的.
    假如外部要写入一个需要查询数据库的, 那么写进B列表, 假如外部写入一个不需要查询数据库的, 写入A列表, 同时, B列表的读取线程, 也会在生成数据后向A列表写入数据, 这样就可以建立一个流水线的模式.但这种情况下, 很明显B列表的读取会成为瓶颈. 因为访问数据库后, 还要进行很多次的A列表插入操作, 这个插入操作的过程, 很明显还是可以让其他线程继续访问数据库的, 所以B列表的读取处理应该是并行多个线程的, 但A线程就没什么必要进行并行, 因为只简单处理后放到"共享区"而已. 而读取"共享区"的写线程, 看你的服务器速度如何了, 可以多个并行写入, 也可以单行, 视"共享区"的流量而定. 一个线程全速工作就可以完成的话, 没有必要多开线程. 哪里需要并行, 就看你具体的业务需求. 只要抓住一点: 到底一个列表, 是需要多读还是单读, 多写还是单写, 这样线程模型就不会乱, 也不会错. 用实际的业务来代入线程模型来理解是只会带来混乱的. 线程模型假设为数学的话, 业务就是物理. 物理是通过数学手段来解决计算的, 但数学本身, 只代表数字不存在其他意义, 套入物理后才有了实际的意义.
      

  10.   

    非常感谢您的耐心指导。我现在明白多了。我之前对队列AB的访问是交叉访问的。所以有些乱。如你所说,完全可以将对A,B访问,流水话。