如何设计Crawler(二)多线程并发设计

这篇干货超级多,多线程大全!含睡眠(Sleep),条件变量(Conditional Variable),信号量(Semaphore),先mark一下!

上一次我们已经讲了Crawler的设计,得到了图中这个架构。Scheduler负责调度Crawler,给Crawler分配任务。那么Scheduler是如何进行调度的呢?每个Crawler是一个线程,所以这就是一个多线程的问题。

先讲睡眠(Sleep)。Crawler共享taskTable和pageTable,Crawler从taskTable获取任务,将爬到的页面写入pageTable,如果页面里包含新的url需要爬取,就将新的url写入taskTable。

过程是这样的,首先Crawler去taskTable查看一下有没有任务,如果没有任务就睡一秒再查看,直到有新的任务。有新的任务就执行新的任务,将爬到的page写到pageTable里,如果有新的task就写到taskTable里。

因为table是共享的,如果多个线程同时读写肯定有问题,所以就要给table加锁,读写完毕后要释放锁。

睡眠的问题是什么呢?睡眠比较死板,说睡一秒就睡一秒,如果一秒之中有新的任务来也不能立即执行。所以有没有一个闹钟的机制,如果有新任务来就把Crawler唤醒呢?有的,用条件变量(Conditional Variable)。

看红字的部分,如果没有新任务,就进入Cond_Wait,这个线程就被block掉,直到有新任务产生,触发了Cond_Signal,就会唤醒等待的线程。

{width="6.0in" height="3.5419630358705163in"}

再看信号量(Semaphore),信号量是简化的条件变量。设定新任务数为信号量,当新任务数小于等于零时,表示没有新任务,进入Wait;否则有新任务,就执行新任务。当有新任务产生时就更改信号量,然后Signal。

{width="6.0in" height="3.5596937882764657in"}

results matching ""

    No results matching ""