zoukankan      html  css  js  c++  java
  • 使用线程池获取执行结果,CountDownLatch+ThreadPool,FutureTask+ThreadPool 并比较

    代码前提:

    BillElectronicItemAttachment只是一个普通的实体类

    CountDownLatch+ThreadPool代码

    线程代码:

    package com.tuniu.app.thread;
    
    import com.tuniu.BillElectronicItemAttachment;
    
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    
    public class UploadImageThread implements Runnable{
        public static final String IMAGE_START = "image/";
        private List<BillElectronicItemAttachment> resultList;
        private CountDownLatch countDownLatch;
        private String paramStr;
    
        public UploadImageThread(List<BillElectronicItemAttachment> resultList, CountDownLatch countDownLatch,String paramStr) {
            this.resultList = resultList;
            this.countDownLatch = countDownLatch;
            this.paramStr = paramStr;
        }
    
        @Override
        public void run() {
            try {
                BillElectronicItemAttachment billElectronicItemAttachment = new BillElectronicItemAttachment();
                billElectronicItemAttachment.setFileName(paramStr);
                resultList.add(billElectronicItemAttachment);
                Thread.sleep(2);
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                countDownLatch.countDown();
            }
        }
    }

    测试方法:

        private static void countThreadTest(ThreadPoolExecutor threadPoolExecutor, CountDownLatch countDownLatch, List<BillElectronicItemAttachment> list) throws InterruptedException {
            for (int i = 0; i < 2000; i++) {
                Integer v = (int) (Math.random() * 100000);
                threadPoolExecutor.execute(new UploadImageThread(list, countDownLatch, v.toString()));
            }
            countDownLatch.await();
        }

    FutureTask+ThreadPool 代码:

    线程代码:

    package com.tuniu.app.thread;
    
    import java.util.concurrent.Callable;
    
    public class UploadImageThreadSubmit implements Callable<String> {
        private String paramStr;
    
        public UploadImageThreadSubmit(String paramStr) {
            this.paramStr = paramStr;
        }
    
        @Override
        public String call() throws InterruptedException {
            Thread.sleep(2);
            return paramStr;
        }
    }

    测试方法:

        private static void callableTest(ThreadPoolExecutor threadPoolExecutor, List<BillElectronicItemAttachment> list) throws ExecutionException, InterruptedException {
            List<FutureTask> futureTasks = new ArrayList<FutureTask>();
            for (int i = 0; i < 2000; i++) {
                Integer v = (int) (Math.random() * 100000);
                FutureTask<String> stringFutureTask = new FutureTask<String>(new UploadImageThreadSubmit(v.toString()));
                threadPoolExecutor.execute(stringFutureTask);
                futureTasks.add(stringFutureTask);
            }
            for (FutureTask futureTask : futureTasks) {
                BillElectronicItemAttachment billElectronicItemAttachment = new BillElectronicItemAttachment();
                billElectronicItemAttachment.setFileName((String) futureTask.get());
                list.add(billElectronicItemAttachment);
            }
        }

    测试代码:

        public static void main(String[] args) throws InterruptedException, ExecutionException {
            for (int i = 0; i < 20; i++) {
                long start = System.currentTimeMillis();
                ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 8, 10000L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(100), new ThreadPoolExecutor.CallerRunsPolicy());
                CountDownLatch countDownLatch = new CountDownLatch(20);
                List<BillElectronicItemAttachment> list = Collections.synchronizedList(new ArrayList<BillElectronicItemAttachment>());
                countThreadTest(threadPoolExecutor, countDownLatch, list);
    //            callableTest(threadPoolExecutor, list);
                System.out.println("我结束了:" + (System.currentTimeMillis() - start));
                threadPoolExecutor.shutdown();
            }
    
        }

    结果对比:

    结论:

      CountDownLatch+ThreadPool稍快,无论是第一次执行,还是后续的执行

    原因:

      FutureTask+ThreadPool 最后有一步循环获取的动作 billElectronicItemAttachment.setFileName((String) futureTask.get()); ,很费时间

    使用CountDownLatch+ThreadPool必读:

    正常情况下,在 Java 中入参是不建议用做返回值的。除了造成代码不易理解、语义不清等问题外,可能还埋下了陷阱等你入坑。

    先来看下编程语言中关于参数传递的类型:

    • 值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

    • 引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

     

    一旦传入的对象被重新赋值,那就无法拿到结果;

    例如:

        @Override
        public void run() {
            try {
                resultList = new ArrayList<>();
                Thread.sleep(2);
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                countDownLatch.countDown();
            }
        }

    类似的处理还有 String a = "ww";

    举一个jdk8易出错的场景:

    resultList = resultList.stream().collect(Collectors.toList());

    所以使用 java8 的时候一定要谨慎

  • 相关阅读:
    跨浏览器的事件对象(EventUtil)
    原型 Object.create
    DC大牛的function扩展
    事件代理 proxy
    错误处理程序
    JQuery 插件
    关于ClownFish的问题
    C#拾遗
    Jquery技巧
    防盗链
  • 原文地址:https://www.cnblogs.com/lzghyh/p/15268494.html
Copyright © 2011-2022 走看看