管理線程池處理任務的返回結果的兩種方法

一、實現線程的幾種方式

        初級階段我們創建線程主要有兩種方法:一種是直接繼承Thread類,一種是實現Runnable接口,但是這兩種方法都無法返回執行結果;如果需要獲取執行結果,就必須通過共享變量或者使用線程通信的方式來達到效果,實現起來比較麻煩。

        在java1.5之後,就提供了Callable和Future,通過這兩種方法可以在執行結束後返回執行結果。

二、管理併發線程的返回結果

        如果在併發執行的任務中,並且每個任務之後都需要獲取結果,有兩種方式可以實現:
        第一種:通過一個list保存一組future,循環查看結果,future不一定完成,如果沒有完成,則調用get會發生阻塞;這樣如果排在前面的任務沒有完成,就會發生阻塞,後面已經完成的任務就無法獲取結果了,例如:
public static void test1() throws ExecutionException,InterruptedException{
          ExecutorService exe = Executors.newFixedThreadPool(5);
          List<Future<String>> result = new ArrayList<>();
          Random random = new Random();
           for(int i = 0 ; i < 10 ; i++){
               result.add( exe.submit(() -> {
                   Thread. sleep(random.nextInt(10000));
                    return Thread.currentThread().getName();
              }));
          }
          System. out.println("begin to get result:" );
           int count = 0;
           for(Future<String> f : result ){
              System. out.println(f .get());
               count++;
          }
          System. out.println("task has done:" +count );
          exe .shutdown();
     }

        改進:future獲取結果之前先判斷future是否執行完畢(f.isDone()),如果執行完成,獲取結果之後,則從執行列表中刪除任務。
        第二種方法:使用ExecutorCompletionService來管理線程池執行任務的執行結果,例如:
public static void test2() throws ExecutionException,InterruptedException{
          ExecutorService exe = Executors.newFixedThreadPool(5);
          ExecutorCompletionService<String> ecs = new ExecutorCompletionService<>(exe );
          Random random = new Random();
           for(int i = 0 ; i < 10 ; i++){
               ecs.submit(() -> {
                   Thread. sleep(random.nextInt(10000));
                    return Thread.currentThread().getName ();
              });
          }
          System. out.println("begin to get result" );
           int count = 0;
           for(int i = 0 ; i < 10 ; i++){
              Future<String> f = ecs.take();
              System. out.println(f .get());
               count++;
          }
          System. out.println("task has done:" +count );
           exe.shutdown();
     }
        ExecutorCompletionService類將Executor與BlockQueue結合在一起,每個線程完成後,會將其返回值放在阻塞隊列中;通過使用阻塞隊列的take或poll方法,就可以獲得結果。當阻塞隊列中不存在元素時,這兩個操作會阻塞,一旦有結果加入,一有結果就會立即返回。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章