美文网首页
ExecutorService.submit(Callable)

ExecutorService.submit(Callable)

作者: 小柠檬真酸 | 来源:发表于2018-01-23 15:48 被阅读880次

    ExecutorService.submit(Callable).get()不并发执行

    开发Java接口处理数据,运行一次要90秒左右,准备用多线程并发执行,最后获取结果集输出

    应为Thread和Runnable两种方法都只能运行多线程,但不能获取结果,没有返回值

    选择了Callable方法,在编程过程中,发现ExecutorService.submit(Callable).get()使用后,并不会并发执行,而是等一个线程执行完,另一线程继续执行。

    网上查找看到一博主有类似情况,学习了

    public class CallableTry {
    
        class Task implements Callable<Long> {
            private long times;
            private String name;
    
            public Task(long times, String name) {
                this.name = name;
                this.times = times;
            }
    
            @Override
            public Long call() {
                System.out.println(name + "开始执行, time[" + times + "]...");
                long before = System.currentTimeMillis();
                for (int i = 0; i < times; i++)
                    ;
                long after = System.currentTimeMillis();
                System.out.println(name + "执行结束.");
                long cost = after - before;
                System.out.println(name + "耗时 :" + cost);
                return cost;
            }
        }
    
        /**
         * @param args
         */
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            long total = 0;
            CallableTry tr = new CallableTry();
            ExecutorService pool = Executors.newCachedThreadPool();
            Random rand = new Random();
            int count = 10;
            for (int i = 0; i < count; i++) {
                total += pool.submit(tr.new Task(10000000 * rand.nextInt(100), i + "任务")).get();
                System.out.println("next task...");
            }
            pool.shutdown();
            while (!pool.isTerminated())
                ;
            System.out.println("耗时:" + total + "毫秒, 平均用时:" + total * 1.0 / count + "毫秒");
        }
    
    }
    

    输出结果:

    0任务开始执行, time[320000000]...
    0任务执行结束.
    0任务耗时 :169
    next task...
    1任务开始执行, time[180000000]...
    1任务执行结束.
    1任务耗时 :96
    next task...
    2任务开始执行, time[950000000]...
    2任务执行结束.
    2任务耗时 :469
    next task...
    3任务开始执行, time[440000000]...
    3任务执行结束.
    3任务耗时 :224
    next task...
    4任务开始执行, time[500000000]...
    4任务执行结束.
    4任务耗时 :243
    next task...
    5任务开始执行, time[700000000]...
    5任务执行结束.
    5任务耗时 :334
    next task...
    6任务开始执行, time[930000000]...
    6任务执行结束.
    6任务耗时 :486
    next task...
    7任务开始执行, time[110000000]...
    7任务执行结束.
    7任务耗时 :56
    next task...
    8任务开始执行, time[820000000]...
    8任务执行结束.
    8任务耗时 :433
    next task...
    9任务开始执行, time[320000000]...
    9任务执行结束.
    9任务耗时 :158
    next task...
    耗时:2668毫秒, 平均用时:266.8毫秒
    

    可以看到执行结果不是并发执行,而是等一个线程执行结束,下一线程才开始运行

    看了下面的评论

    ExecutorService.submit(Callable)返回一个Future对象,而Future.get()方法是等到Future对应的线程执行完后获取结果数据。

    也就是说get()方法在得不到数据前不会退出,其后的代码也无法执行。

    for (int i = 0; i < count; i++) {
        total += pool.submit(
        tr.new Task(10000000 * rand.nextInt(100), i + "任务")).get();
        System.out.println("next task...");
    }
    

    代码中for()循环直接调用get(),每次执行自然要等到get()方法获取到数据才能执行下次循环,是手动把并发改成了同步执行

    只要把.get()方法拿到for循环外读取数据,就可以并发执行。

    int count = 10;
            Future[] futures = new Future[count];
            for (int i = 0; i < count; i++) {
                futures[i] = pool.submit(tr.new Task(1 * rand.nextInt(100), i
                        + "任务"));
            }
    

    修改代码如下:

    public class CallableTry02 {
    
        class Task implements Callable<Long> {
            private long times;
            private String name;
    
            public Task(long times, String name) {
                this.name = name;
                this.times = times;
            }
    
            @Override
            public Long call() {
                System.out.println(name + "开始执行, time[" + times + "]...");
                long before = System.currentTimeMillis();
                for (int i = 0; i < times; i++);
                long after = System.currentTimeMillis();
                System.out.println(name + "执行结束.");
                long cost = after - before;
                System.out.println(name + "耗时 :" + cost);
                return cost;
            }
        }
    
        /**
    //   * @param args
         */
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            long total = 0;
            CallableTry02 tr = new CallableTry02();
            ExecutorService pool = Executors.newCachedThreadPool();
            Random rand = new Random();
            int count = 10;
            Future[] futures = new Future[count];
            for (int i = 0; i < count; i++) {
    //          total += pool.submit(tr.new Task(10000000 * rand.nextInt(100), i + "任务")).get();
                futures[i]= pool.submit(tr.new Task(10000000 * rand.nextInt(100), i + "任务"));
                
                
                
                System.out.println("next task...");
            }
            pool.shutdown();
            while (!pool.isTerminated());
            System.out.println("耗时:" + total + "毫秒, 平均用时:" + total * 1.0 / count + "毫秒");
        }
    
    }
    

    运行结果显示,可以并发执行:

    next task...
    0任务开始执行, time[460000000]...
    next task...
    1任务开始执行, time[380000000]...
    next task...
    next task...
    2任务开始执行, time[30000000]...
    next task...
    next task...
    next task...
    next task...
    6任务开始执行, time[510000000]...
    next task...
    next task...
    3任务开始执行, time[650000000]...
    2任务执行结束.
    2任务耗时 :37
    5任务开始执行, time[270000000]...
    4任务开始执行, time[770000000]...
    7任务开始执行, time[180000000]...
    9任务开始执行, time[610000000]...
    8任务开始执行, time[120000000]...
    8任务执行结束.
    8任务耗时 :267
    7任务执行结束.
    7任务耗时 :448
    5任务执行结束.
    5任务耗时 :504
    1任务执行结束.
    1任务耗时 :802
    6任务执行结束.
    6任务耗时 :889
    0任务执行结束.
    0任务耗时 :930
    9任务执行结束.
    9任务耗时 :851
    3任务执行结束.
    3任务耗时 :987
    4任务执行结束.
    4任务耗时 :1061
    

    原网址:
    [1]: https://www.cnblogs.com/adaikiss/archive/2010/12/24/1915735.html

    相关文章

      网友评论

          本文标题:ExecutorService.submit(Callable)

          本文链接:https://www.haomeiwen.com/subject/hyysaxtx.html