当前位置: 首页 > news >正文

重庆建设厂招工信息网站手机网站演示

重庆建设厂招工信息网站,手机网站演示,视频拍摄方法有哪些,北京中高端网站建设公司前言 在java项目开发过程中经常会遇到比较耗时的任务#xff0c;通常是将这些任务做成异步操作#xff0c;在java中实现异步操作有很多方法#xff0c;本文主要总结一些常用的处理方法。为了简化#xff0c;我们就拿一个实际的案例#xff0c;再用每种方法去实现#xf…前言 在java项目开发过程中经常会遇到比较耗时的任务通常是将这些任务做成异步操作在java中实现异步操作有很多方法本文主要总结一些常用的处理方法。为了简化我们就拿一个实际的案例再用每种方法去实现对比看看这些方法有什么优缺点。 具体案例 在C://img/url.txt中有1000个图片URL我们需要将这些图片下载到C://img/download目录下。 需要将每张图片耗时累加起来输出最后的时间 img.txt数据格式 https://a.com/1.jpg https://a.com/2.jpg https://a.com/3.jpg ... 计算Demo 比如 下载1.jpg 耗时1ms ,下载 2.jpg耗时2ms…下载 n.jpg耗时 n ms 最终我们总耗时 123…1000500500ms 公共方法 为了方便测试我们先定义一个DownloadImg下载接口 public interface DownloadImg {/**** param urls 需要下载图片的url* return 所有图片下载总耗时ms*/Long download(ListString urls) throws Exception ;/**** param url 下载单个图片的URL* return 下载单张图片耗时 ms*/Long download(String url) throws Exception;/*** 关闭线程池*/void shutdown() throws InterruptedException;/*** 提交任务* param task* return*/Future? submit(Runnable task); }为了简化下载、创建线程池、时间累加等操作我们抽象一些共用方法 public abstract class AbstractDownloadImg implements DownloadImg {//总耗时public AtomicLong sumTimenew AtomicLong(0L);public ExecutorService executorService Executors.newFixedThreadPool(10);private AtomicInteger i new AtomicInteger(1);public Long download(String url) {try {Long startTime System.currentTimeMillis();FileUtils.copyURLToFile(new URL(url), new File(String.format(C:\img\download\%s.jpg, i.getAndIncrement())));Long castTime System.currentTimeMillis() - startTime;System.out.println(Thread.currentThread().getName() download : url success, cast : castTime ms);return castTime;} catch (Exception e) {e.printStackTrace();return 0L;}}public void shutdown() throws InterruptedException {Thread.sleep(1000L);executorService.shutdown();}public Future? submit(Runnable task) {return executorService.submit(task);} }具体实现 一. 使用Future任务多线程下载 这种方法很是自然而然能想到文件中有1000个图片单个线程依次去下载太慢了于是我们可以把1000张图片分成10个子任务每个子任务去下载100张图片子任务中把这100张图片耗时加起来然后再把这10个子任务的耗时相加就是总时长了。 public class MultiThreadDownload extends AbstractDownloadImg implements DownloadImg {Overridepublic Long download(ListString imgUrls) throws Exception {//每100个一组ListListString urls Lists.partition(imgUrls, 100);//每个线程下载100张图片耗时返回结果ListFutureLong futures new ArrayList();//分成10个线程每个线程下载100个urls.forEach(subUrls-{FutureTaskLong future new FutureTask(() - subUrls.stream().map(this::download).mapToLong(x-x).sum());//反回结果添加到futures中futures.add(future);//提交到线程池中submit(future);});//每线程耗时时间累加for(FutureLong f:futures){sumTime.getAndAdd(f.get());}return sumTime.get();} }优点 比较简单大部人第一眼能想到的方法 缺点 会产生水桶效应。如果前9个线程下载的都是小图片很快下载完成了第10个线程全是大图片当最后9个线都空着时第10个线程任务可能还在等待 二. CompletableFuture 上面的方法是我们自己写Future然后拿到返回值相加在JUC包下面有个CompletableFuture我们可以直接拿来用。 public class CompletableFutureDownload extends AbstractDownloadImg implements DownloadImg {Overridepublic Long download(ListString imgUrls) {//创建10个CompletableFutureCompletableFutureLong[] completableFutures new CompletableFuture[imgUrls.size()];for (int i 0; i imgUrls.size(); i) {String url imgUrls.get(i);completableFutures[i] CompletableFuture.supplyAsync(() - download(url), executorService).whenComplete((k, v) - sumTime.getAndAdd(k));}//所有任务合成一个CompletableFutureCompletableFuture allFuture CompletableFuture.allOf(completableFutures).whenComplete((k, v) - {System.out.println(all future complete cast: {} sumTime.get() ms);});//等待所有任务完成allFuture.join();return sumTime.get();} }三. 使用CountDownLatch 使用Futrue获取线程池返回结果还是有点麻烦的在JUC包中有个CountDownLatch(倒计数门闩),使用这个实现代码就简化很多了我们只需要把每张图片下载耗时累加起来最后等待所有任务完成就OK了。 public class CountDownLatchDownload extends AbstractDownloadImg implements DownloadImg {Overridepublic Long download(ListString imgUrls) throws Exception {//门栓计数次CountDownLatch countDownLatch new CountDownLatch(imgUrls.size());//总耗时AtomicLong sumTime new AtomicLong(0L);for (String url : imgUrls) {submit(() - {try {sumTime.getAndAdd(download(url));} finally {countDownLatch.countDown();}});}//等待所有任务结束countDownLatch.await();return sumTime.get();} }四. 使用lambda中的parallelStream 有了上面倒计数门闩那我们自然可以想到JAVA8 lambda中的parallelStream了用了parallelStream上面的代码又可以简化了。 public class ParallelStreamDownload extends AbstractDownloadImg implements DownloadImg {Overridepublic Long download(ListString imgUrls) throws Exception {return imgUrls.parallelStream().mapToLong(this::download).sum();} }需要注意的地parallelStream底层实现是使用的fork join,默认线程数是CPU核数而且是全局共用一个线程池的这点很重要如果不指定线程池项目别处使用了parallelStream可能影响你你当前这处代码的执行速度。当然我们可以设置默认线程数和指定线程池。 //设置parallelStream线程数量为20个 System.setProperty(java.util.concurrent.ForkJoinPool.common.parallelism, 20);指定ForkJoinPool的parallelStream public class ParallelStreamDownload extends AbstractDownloadImg implements DownloadImg {Overridepublic Long download(ListString imgUrls) throws Exception {ForkJoinPool forkJoinPool new ForkJoinPool(20);return forkJoinPool.submit(() - imgUrls.parallelStream().mapToLong(this::download).sum()).get();} }优点 代码非常简洁 缺点 隐藏了很多细节使用不当可能导致不可预估的后果如果不了解内部原理你都不知道为什么你的代码卡住了 五. 使用Fork/Join parallelStream底层就是用的Fork/Join来实现的所以我们也可以自己用Fork/Join来实现。 public class ForkJoinDownload extends AbstractDownloadImg implements DownloadImg {static class DownloadJoinTask extends RecursiveTaskLong {//需要下载的URLprivate ListString urls;//子任务最多条数private Integer MAX_TASK_COUNT 100;private DownloadImg downloadImg;public DownloadJoinTask(ListString urls, DownloadImg downloadImg) {this.urls urls;this.downloadImg downloadImg;}Overrideprotected Long compute() {//当前任务100个执行下载操作if (urls.size() MAX_TASK_COUNT) {return urls.stream().map(x - {try {return downloadImg.download(x);} catch (Exception e) {e.printStackTrace();return 0L;}}).mapToLong(x - x).sum();} else {//当前前任务拆分成两个任务ForkJoinDownload.DownloadJoinTask leftTask new ForkJoinDownload.DownloadJoinTask(urls.subList(0, urls.size() / 2), downloadImg);ForkJoinDownload.DownloadJoinTask rightTask new ForkJoinDownload.DownloadJoinTask(urls.subList(urls.size() / 2, urls.size()), downloadImg);//提交子任务invokeAll(leftTask, rightTask);return leftTask.join() rightTask.join();}}}Overridepublic Long download(ListString imgUrls) throws Exception {ForkJoinPool forkJoinPool new ForkJoinPool(20);DownloadJoinTask downloadJoinTask new DownloadJoinTask(imgUrls, this);ForkJoinTaskLong taskFuture forkJoinPool.submit(downloadJoinTask);sumTime.addAndGet(taskFuture.get());return sumTime.get();} }优点 工作窃取算法,不会产生水桶效应 缺点 需要正确理解Fork/Join模型的任务执行逻辑才能写出好代码有一定的门槛 测试代码 public static void main(String[] args) throws Exception {ListString urls FileUtils.readLines(new File(C:\img\url.txt), Charset.defaultCharset());//DownloadImg downloadImgnew MultiThreadDownload();//DownloadImg downloadImgnew CountDownLatchDownload();//DownloadImg downloadImgnew ParallelStreamDownload();//DownloadImg downloadImgnew ForkJoinDownload();DownloadImg downloadImg new CompletableFutureDownload();System.out.println(download all url cast: downloadImg.download(urls) ms);downloadImg.shutdown(); }总结 本文主要通过下载图片这个具体的案例介绍JAVA中5种常用的方法如何异步处理比较耗时的任务并对比了优缺点希望在项目过遇到类似的需求可以帮助你找到合适的方法。
http://www.w-s-a.com/news/398884/

相关文章:

  • 北京市保障房建设投资中心网站淄博哪个网站做房屋出赁好
  • 如何做网站的优化网站开发怎么收费
  • 网站的关键词怎么选择2345实用查询
  • 免费的制作网站做图剪片文案网站app接单
  • 中国有多少网站有多少域名上海网站建设网页制作邢台
  • 网站 数据报表如何做室内设计联盟官方网站入口
  • 怎样建设网站论文合肥做网站的软件公司
  • 收款后自动发货的网站是怎么做的怎么看网站后台网页尺寸
  • 谷歌seo引擎优化宁波seo关键词
  • 外贸网站建设需要注意什么seo课程
  • 做信息图网站网站建设的软件介绍
  • 网站开发语言数据库有几种魏县审批建设的网站
  • 北京公司网站建设推荐海口建设
  • 不懂编程如何做网站婚礼网站模板
  • 像京东一样的网站wordpress入门视频教程7 - 如何在文章里加入视频和音乐
  • 惠州网站建设排名wordpress3万篇文章优化
  • 创建网站的三种方法北京建王园林工程有限公司
  • jsp网站建设模板下载十大免费excel网站
  • 网络公司网站图片网站建立好了自己怎么做优化
  • 云主机是不是可以搭建无数个网站百度快速seo优化
  • 房地产怎么做网站推广建立音乐网站
  • 川畅科技联系 网站设计网站开发的教学视频
  • 为什么学网站开发凡科登陆
  • 设计师常备设计网站大全中山精品网站建设信息
  • 杭州建设工程网seo服务是什么
  • 兼职做问卷调查的网站wordpress mysql设置
  • 怎么在百度上能搜到自己的网站山西seo谷歌关键词优化工具
  • 网站搭建免费模板飞鱼crm下载
  • 网站开发竞品分析app制作公司深圳
  • 网站建设ssc源码修复设计班级网站建设