zoukankan      html  css  js  c++  java
  • java中异步调用注意

    Future接口是Java标准API的一部分,在java.util.concurrent包中。Future接口是Java线程Future模式的实现,可以来进行异步计算。

    有了Future就可以进行三段式的编程了,1.启动多线程任务2.处理其他事3.收集多线程任务结果。从而实现了非阻塞的任务调用。在途中遇到一个问题,那就是虽然能异步获取结果,但是Future的结果需要通过isdone来判断是否有结果,或者使用get()函数来阻塞式获取执行结果。这样就不能实时跟踪其他线程的结果状态了,所以直接使用get还是要慎用,最好配合isdone来使用。如果直接使用get来获取结果, get是阻塞操作, 相当于获取结果仍然是同步.因此在获取结果的时候需要注意.

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * 多线程执行,异步获取结果
     * 
     * @author i-clarechen
     *
     */
    public class AsyncThread {
    
        public static void main(String[] args) {
            AsyncThread t = new AsyncThread();
            List<Future<String>> futureList = new ArrayList<Future<String>>();
            t.generate(3, futureList);
            t.doOtherThings();
            t.getResult(futureList);
        }
    
        /**
         * 生成指定数量的线程,都放入future数组
         * 
         * @param threadNum
         * @param fList
         */
        public void generate(int threadNum, List<Future<String>> fList) {
            ExecutorService service = Executors.newFixedThreadPool(threadNum);
            for (int i = 0; i < threadNum; i++) {
                Future<String> f = service.submit(getJob(i));
                fList.add(f);
            }
            service.shutdown();
        }
    
        /**
         * other things
         */
        public void doOtherThings() {
            try {
                for (int i = 0; i < 3; i++) {
                    System.out.println("do thing no:" + i);
                    Thread.sleep(1000 * (new Random().nextInt(10)));
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 从future中获取线程结果,打印结果
         * 
         * @param fList
         */
        public void getResult(List<Future<String>> fList) {
            ExecutorService service = Executors.newSingleThreadExecutor();
            service.execute(getCollectJob(fList));
            service.shutdown();
        }
    
        /**
         * 生成指定序号的线程对象
         * 
         * @param i
         * @return
         */
        public Callable<String> getJob(final int i) {
            final int time = new Random().nextInt(10);
            return new Callable<String>() {
                @Override
                public String call() throws Exception {
                    Thread.sleep(1000 * time);
                    return "thread-" + i;
                }
            };
        }
    
        /**
         * 生成结果收集线程对象
         * 
         * @param fList
         * @return
         */
        public Runnable getCollectJob(final List<Future<String>> fList) {
            return new Runnable() {
                public void run() {
                    for (Future<String> future : fList) {
                        try {
                            while (true) {
                                if (future.isDone() && !future.isCancelled()) {
                                    System.out.println("Future:" + future
                                            + ",Result:" + future.get());
                                    break;
                                } else {
                                    Thread.sleep(1000);
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
        }
    
    }
    优化获取方式:
          List<Object> results = null;
            int retryLimit = 3;
            long delay = 10;
            int tryTime = 0;
        for(Future future : futures)
            do {
                try {
                //此处原理:
                    results = future.get();
                } catch (Exception e) {
                    results = null;
                }
    
                tryTime++;
                if (results == null) {
                    try {
                        Thread.sleep(delay << tryTime);
                    } catch (InterruptedException e) {
    
                    }
                }
            } while (results == null && tryTime < retryLimit);
        }
            return results;

    运行结果打印和future放入列表时的顺序一致,为0,1,2:

    do thing no:0
    do thing no:1
    do thing no:2
    Future:java.util.concurrent.FutureTask@68e1ca74,Result:thread-0
    Future:java.util.concurrent.FutureTask@3fb2bb77,Result:thread-1
    Future:java.util.concurrent.FutureTask@6f31a24c,Result:thread-2

    使用CompletionService,它内部添加了阻塞队列,从而获取future中的值,然后根据返回值做对应的处理

    下面是先执行完的线程先处理的方案:

    import java.util.Random;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.Callable;
    import java.util.concurrent.CompletionService;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorCompletionService;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.LinkedBlockingDeque;
    
    
    public class testCallable {
        public static void main(String[] args) {
            try {
                completionServiceCount();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    
      
        /**
         * 使用completionService收集callable结果
         * @throws ExecutionException 
         * @throws InterruptedException 
         */
        public static void completionServiceCount() throws InterruptedException, ExecutionException {
            ExecutorService executorService = Executors.newCachedThreadPool();
            CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(
                    executorService);
            int threadNum = 5;
            for (int i = 0; i < threadNum; i++) {
                completionService.submit(getTask(i));
            }
            int sum = 0;
            int temp = 0;
            for(int i=0;i<threadNum;i++){
                temp = completionService.take().get();
                sum += temp;
                System.out.print(temp + "	");
            }
            System.out.println("CompletionService all is : " + sum);
            executorService.shutdown();
        }
    
        public static Callable<Integer> getTask(final int no) {
            final Random rand = new Random();
            Callable<Integer> task = new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    int time = rand.nextInt(100)*100;
                    System.out.println("thead:"+no+" time is:"+time);
                    Thread.sleep(time);
                    return no;
                }
            };
            return task;
        }
    }

    运行结果为最先结束的线程结果先被处理:

    thead:0 time is:4200
    thead:1 time is:6900
    thead:2 time is:2900
    thead:3 time is:9000
    thead:4 time is:7100
    2    0    1    4    3    CompletionService all is : 10
  • 相关阅读:
    【Android 界面效果23】LayoutInflater作用及使用
    【Android Api 翻译4】android api 完整翻译之Contacts Provider (学习安卓必知的api,中英文对照)
    【Android Api 翻译3】android api 完整翻译之Application Fundamentals (学习android必须知道的)
    【Mood-7】tell 2 my gf-miss u not sudden but always
    Android权限机制
    【Mood-6】空气显示触摸屏、智能钱夹
    【Android 界面效果22】Android的Tab与TabHost
    【Android 界面效果21】Android ViewPager使用详解
    【Android 界面效果20】Android GradientDrawable类的详解,设置activity的背景颜色渐变效果
    【Android 界面效果19】Android中shape的使用
  • 原文地址:https://www.cnblogs.com/kexianting/p/11662089.html
Copyright © 2011-2022 走看看