<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java多線程之Callable和Future

          共 4739字,需瀏覽 10分鐘

           ·

          2022-06-29 15:46

          本篇說(shuō)明的是Callable和Future,它倆很有意思的,一個(gè)產(chǎn)生結(jié)果,一個(gè)拿到結(jié)果。 

          Callable接口類(lèi)似于Runnable,從名字就可以看出來(lái)了,但是Runnable不會(huì)返回結(jié)果,并且無(wú)法拋出返回結(jié)果的異常,而Callable功能更強(qiáng)大一些,被線程執(zhí)行后,可以返回值,這個(gè)返回值可以被Future拿到,也就是說(shuō),F(xiàn)uture可以拿到異步執(zhí)行任務(wù)的返回值,下面來(lái)看一個(gè)簡(jiǎn)單的例子:

          public class CallableAndFuture {

              public static void main(String[] args) {

                  Callable<Integer> callable = new Callable<Integer>() {

                      public Integer call() throws Exception {

                          return new Random().nextInt(100);

                      }

                  };

                  FutureTask<Integer> future = new FutureTask<Integer>(callable);

                  new Thread(future).start();

                  try {

                      Thread.sleep(5000);// 可能做一些事情

                      System.out.println(future.get());

                  } catch (InterruptedException e) {

                      e.printStackTrace();

                  } catch (ExecutionException e) {

                      e.printStackTrace();

                  }

              }

          }

          FutureTask實(shí)現(xiàn)了兩個(gè)接口,Runnable和Future,所以它既可以作為Runnable被線程執(zhí)行,又可以作為Future得到Callable的返回值,那么這個(gè)組合的使用有什么好處呢?假設(shè)有一個(gè)很耗時(shí)的返回值需要計(jì)算,并且這個(gè)返回值不是立刻需要的話,那么就可以使用這個(gè)組合,用另一個(gè)線程去計(jì)算返回值,而當(dāng)前線程在使用這個(gè)返回值之前可以做其它的操作,等到需要這個(gè)返回值時(shí),再通過(guò)Future得到,豈不美哉!這里有一個(gè)Future模式的介紹:http://openhome.cc/Gossip/DesignPattern/FuturePattern.htm。 

          下面來(lái)看另一種方式使用Callable和Future,通過(guò)ExecutorService的submit方法執(zhí)行Callable,并返回Future,代碼如下:

          public class CallableAndFuture {

              public static void main(String[] args) {

                  ExecutorService threadPool = Executors.newSingleThreadExecutor();

                  Future<Integer> future = threadPool.submit(new Callable<Integer>() {

                      public Integer call() throws Exception {

                          return new Random().nextInt(100);

                      }

                  });

                  try {

                      Thread.sleep(5000);// 可能做一些事情

                      System.out.println(future.get());

                  } catch (InterruptedException e) {

                      e.printStackTrace();

                  } catch (ExecutionException e) {

                      e.printStackTrace();

                  }

              }

          }

          代碼是不是簡(jiǎn)化了很多,ExecutorService繼承自Executor,它的目的是為我們管理Thread對(duì)象,從而簡(jiǎn)化并發(fā)編程,Executor使我們無(wú)需顯示的去管理線程的生命周期,是JDK 5之后啟動(dòng)任務(wù)的首選方式。 

          執(zhí)行多個(gè)帶返回值的任務(wù),并取得多個(gè)返回值,代碼如下:

          public class CallableAndFuture {

              public static void main(String[] args) {

                  ExecutorService threadPool = Executors.newCachedThreadPool();

                  CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool);

                  for(int i = 1; i < 5; i++) {

                      final int taskID = i;

                      cs.submit(new Callable<Integer>() {

                          public Integer call() throws Exception {

                              return taskID;

                          }

                      });

                  }

                  // 可能做一些事情

                  for(int i = 1; i < 5; i++) {

                      try {

                          System.out.println(cs.take().get());

                      } catch (InterruptedException e) {

                          e.printStackTrace();

                      } catch (ExecutionException e) {

                          e.printStackTrace();

                      }

                  }

              }

          }

          其實(shí)也可以不使用CompletionService,可以先創(chuàng)建一個(gè)裝Future類(lèi)型的集合,用Executor提交的任務(wù)返回值添加到集合中,最后遍歷集合取出數(shù)據(jù),代碼略。

          這里再闡述一下:提交到CompletionService中的Future是按照完成的順序排列的,這種做法中Future是按照添加的順序排列的。

          所以這兩種方式的區(qū)別在于:

          1. CompletionService.take 會(huì)獲取并清除已經(jīng)完成Task的結(jié)果,如果當(dāng)前沒(méi)有已經(jīng)完成Task時(shí),會(huì)阻塞。

          2. “先創(chuàng)建一個(gè)裝Future類(lèi)型的集合,用Executor提交的任務(wù)返回值添加到集合中,最后遍歷集合取出數(shù)據(jù)”——這種方法通常是按照Future加入的順序。

          兩個(gè)方法最大的差別在于遍歷 Future 的順序,相對(duì)來(lái)說(shuō), CompletionService 的性能更高。考慮如下場(chǎng)景:多線程下載,結(jié)果用Future返回。第一個(gè)文件特別大,后面的文件很小。用方法1,能很快知道已經(jīng)下載完文件的結(jié)果(不是第一個(gè));而用方法2,必須等第一個(gè)文件下載結(jié)束后,才會(huì)獲得其他文件的下載結(jié)果。

          (完)

          Java經(jīng)驗(yàn)總結(jié)

          專(zhuān)注于Java干貨分享

          掃描上方二維碼獲取更多Java干貨



          瀏覽 25
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  草比91 | 日本黄色一区二区三区 | 欧美性爱天天射 | 青娱乐亚洲精品视频 | 99精品免费在线观看 |