public class Program
{
private static BlockingQueue<string> m_Queue = new BlockingQueue<string>();
public static void Main()
{
var thread1 = new Thread(Process);
var thread2 = new Thread(Process);
thread1.Start();
thread2.Start();
while (true)
{
string url = GetNextUrl();
m_Queue.Enqueue(url);
}
}
public static void Process()
{
while (true)
{
string url = m_Queue.Dequeue();
// Do whatever with the url here.
}
}
}
4条答案
按热度按时间9o685dep1#
这样做的标准做法是使用blocking queue。如果你使用的是.NET 4.0,那么你可以利用BlockingCollection类,否则你可以使用Stephen Toub的实现。
您要做的是,根据需要启动尽可能多的工作线程,并让它们在无限循环中循环,在队列中出现项目时对它们进行删除。你的主线将围绕该项目。阻塞队列被设计为等待/阻塞出队操作,直到项目变得可用。
t2a7ltrp2#
当涉及到网络爬虫时,我通常不会有积极的想法.
你想用threadpool。
您只需将工作负载“推入”队列,并让线程池管理它。
zengzsys3#
我不得不说-我不是一个线程Maven,我的C#是相当生 rust -但考虑到需求,我会建议这样的东西:
1.为网站定义一个队列。
1.使用
Crawler
线程定义池。1.主进程遍历网站队列并检索网站地址。
1.从线程池中调用一个可用线程-为它分配网站地址并允许它开始运行。在线程对象中设置一个指示器,它应该等待所有后续线程完成(这样您就不会继续到下一个站点)。
1.一旦所有的线程都结束了-主线程(在步骤#4中开始)将结束并返回到主进程的主循环以继续到下一个网站。
Crawler
的行为应该是这样的:1.调查当前地址的内容
1.将层次结构重定向到当前级别之下
1.对于站点树的当前节点的每个子节点-从池中提取一个新的
crawler
线程,并使用子节点的地址在后台启动它1.如果池为空,则等待线程变为可用。
1.如果线程被标记为等待-等待所有其他线程完成
我认为这里有一些挑战-但作为一个一般的流程,我相信它可以做的工作。
jqjz2hbq4#
把你所有的网址放在一个队列里,每次你处理完前一个网址的时候,从队列中弹出一个。
您还可以将递归链接放在队列中,以便更好地控制一次执行的下载数量。
你可以设置X个工作线程,它们都从队列中获取一个URL,以便一次处理更多的URL。但这样你就可以自己控制了。
你可以在.Net中使用
ConcurrentQueue<T>
来获得一个线程安全队列。