脚本宝典收集整理的这篇文章主要介绍了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(); } }
执行结果:
查看本地文件,顺序和内容也都没有问题:
总结:
多个线程共享变量,只new一个实例,传给多个线程使用;
可以使用atomit类、synchronized、volitaile、lock
保证多线程共享变量的安全性;future.get()
顺序和executorService.submit()
顺序一致,和谁先执行完毕无关
使用callable + future
可以获取线程返回值、捕获;
以上是脚本宝典为你收集整理的java爬取捧腹网段子(多线程版)全部内容,希望文章能够帮你解决java爬取捧腹网段子(多线程版)所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。