使用泛型和并发改善集合 - 编程入门网
个线程另 一个原因。在单独的线程内处理 Set 的每个元素应该可以显著提高整个工作的 处理速度。当然,您需要限制线程的数量,否则将会执行太多的任务,这些任务 之间的交换将会花费更多的时间。
Executor Java SE 5 引入了 java.util.concurrent 库和泛型(请参阅 参考资料)。 Executor 接口接受 Runnable 对象并执行。这类似于将一个 Runnable 对象传 递到 Thread 构造器中,但是借助 Executor,当一个 Thread 处理完一个 Runnable 后,可以重新使用它获得新的 Runnable。因此,该程序避免了不断丢 弃并重新创建线程的过程。Executor 接口有一个 execute() 方法,它接受 Runnable 参数。具体结果取决于 Executor 接口的特定实现。 Executor 的一个实现就是 ThreadPoolExecutor。使用 Executors 工具类来 创建线程池,而不是直接调用 ThreadPoolExecutor 构造器来创建。对于固定大 小的线程池,使用 newFixedThreadPool(int maxThreads);或者使用 newFixedThreadPool(int maxThreads, ThreadFactor factory),它允许您提供 一个用于创建底层线程的工厂。 创建线程池之后,使用 service(Runnable) 方法添加要运行的任务。对于您 创建的 Web crawler,可以调用 awaitTermination() 方法来确定所有任务何时 完成,或者至少确定出线程池何时终止,如清单 6 所示: 清单 6. 使用线程池
awaitTermination() 方法接受一个超时。清单 6 中的程序被设置为五分钟 后超时。根据想要让程序运行多久、网络连接速度和想对网站进行处理的深度, 您可以使用更长或更短的超时。 另外请注意,只有基 URI 字符串被添加到了 crawler。读取每个页面时,会 将新的 URI 添加到作业队列。 Runnable 该服务执行的 Runnable 任务是 清单 5 中的大量代码。我添加了一些额外 的检查,以改进构建下一个页面的 URL 的过程。execute() 方法末尾的检查确 定服务是否应该终止。通常情况下,线程池会运行到程序结束,但是在线程池完 成时这个程序才会结束,所以这个检查非常必要。 下载 CollectUrls 程序,并在一个相对较小的网站上运行它,最好是您自己 的网站,以从该网站获得所有的链接。您也可以修改该程序以保持一个多重映射 :如果您知道每个链接的源,您可以自动生成网站层次和互连的映射。 其他线程池 CollectUrls Web crawler 程序利用一个固定大小的线程池。但它不是惟一 的选择。可以使用 Executors 工具类创建其他三种线程池: newCachedThreadPool() 可创建极大的线程池,但是当线程空闲太久时,它 会终止线程。如果您有很多短期的异步任务,可以考虑使用它。如果线程池中有 可用的线程,它就会被使用。如果没有可用的线程,则会创建一个新线程,然后 如果线程池中的线程空闲了 60 秒,该线程就会消失。当没有进行任何任务时, 不会使用任何资源。相反,当没有任务要完成时,固定大小的线程池会让所有的 线程等待。 newSingleThreadExecutor() 创建的线程池对需要按顺序执行的作业非常有 用。如果底层的线程终止了,它会被重新创建。这类似于创建一个固定大小的线 程池,但是固定大小的线程池无法更改大小。 newScheduledThreadPool() 可以创建像 Timer 对象一样工作的线程池,但 是能够更好地处理未捕获的异常和线程饥饿。借助 Timer 类,您可以拥有一个 长时间运行的 TimerTask,阻止其他任务运行。一个线程池中包含多个线程可以 防止其他任务被阻止 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |