java爬取捧腹网段子(多线程版)

发布时间:2019-11-20 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了java爬取捧腹网段子(多线程版)脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_777_0@

前文链接 : java爬取捧腹网段子

上一篇文章讲述了如何使用Java爬取内容并写入文件,但是速度堪忧,今天将代码搞成了多线程版本,
具体方式如下:

新建一个splider类,继承callable接口,用于存放我们需要多线程执行的逻辑:
将上一篇文章中爬取网页内容的代码搬过来

public class Splider implements Callable {     // 使用atomicInteger保证共享变量的安全自增     private AtomicInteger pageNum = new AtomicInteger(0);      @override     public StringBuilder call() throws Exception {         // 当前页码         Integer privateNum = this.pageNum.addAndGet(1);         // 存储当前页的文本         StringBuilder currentPageText = new StringBuilder();          System.out.println("正在爬取第" + privateNum + "页内容。。。");         String htML = ConnectionUtil.Connect("https://www.pengfu.COM/xiaohua_" + privateNum + ".html");         Document doc = Jsoup.parse(html);         Elements titles = doc.select("h1.dp-b");         for (Element titleEle : titles) {             Element parent = titleEle.parent();             String title = titleEle.getElementsByTag("a").text();             String author = parent.select("p.user_name_list > a").text();             String content = parent.select("div.content-img").text();             // 将内容格式化             currentPageText.append(title)                     .append("rn作者:").append(author)                     .append("rn").append(content)                     .append("rn").append("rn");         }         currentPageText.append("-------------第").append(privateNum).append("页-------------").append("rn");         System.out.println("第" + privateNum + "页内容爬取完毕。。。");         // 将当前页内容返回给future对象         return currentPageText;     } }

主函数:

public static void main(String[] args) throws ExecutionException, InterruptedException {     long startTime = System.currentTimeMillis();     // 创建大小为5的线程池     ExecutorService esPool = Executors.newFixedThreadPool(5);     List<Future<StringBuilder>> futureList = new ArrayList<>();     Splider splider = new Splider();     for (int i = 1; i <= 10; i++) {         futureList.add(esPool.submit(splider));     }      List<StringBuilder> finishCount = new ArrayList<>();     for (Future<StringBuilder> future : futureList) {         // 线程结束,将线程返回的内容添加到list         finishCount.add(future.get());     }      /*      * 所有内容爬取完毕,将内容统一写入磁盘      */     if (finishCount.size() == 10) {         StringBuilder allText = new StringBuilder();         /*          * finishCount中future.get()的顺序 和 futureList中的future顺序一致          * 所以内容是从第1页...第N页顺序写入          */         for (StringBuilder pageNum : finishCount) {             allText.append(pageNum);         }         // 写入磁盘         Test.writeToFile(allText.toString());         long endTime = System.currentTimeMillis();         System.out.println("耗时 : " + (endTime - startTime));         // 关闭线程池         esPool.shutdownNow();     } }

执行结果:

java爬取捧腹网段子(多线程版)

查看本地文件,顺序和内容也都没有问题:

java爬取捧腹网段子(多线程版)

总结:
多个线程共享变量,只new一个实例,传给多个线程使用;
可以使用atomit类、synchronized、volitaile、lock保证多线程共享变量的安全性;
future.get()顺序和executorService.submit()顺序一致,和谁先执行完毕无关
使用callable + future可以获取线程返回值、捕获;

脚本宝典总结

以上是脚本宝典为你收集整理的java爬取捧腹网段子(多线程版)全部内容,希望文章能够帮你解决java爬取捧腹网段子(多线程版)所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。